ASR_BASE

Change-Id: Icf3719cc0afe3eeb3edc7fa80a2eb5199ca9dda1
diff --git a/package/utils/adb/Makefile b/package/utils/adb/Makefile
new file mode 100644
index 0000000..f0f137c
--- /dev/null
+++ b/package/utils/adb/Makefile
@@ -0,0 +1,52 @@
+include $(TOPDIR)/rules.mk
+#Based on adb package from AUR https://aur.archlinux.org/packages/adb/ , reused Makefile
+
+PKG_NAME:=adb
+PKG_SOURCE_VERSION:=6fe92d1a3fb17545d82d020a3c995f32e6b71f9d
+PKG_VERSION:=5.0.2~$(call version_abbrev,$(PKG_SOURCE_VERSION))
+PKG_RELEASE:=3
+
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_URL:=https://android.googlesource.com/platform/system/core
+PKG_MIRROR_HASH:=2ff96b4342cd05f475083207a4927635548c6693771c12a24cfa99f175fdb10a
+
+PKG_MAINTAINER:=Henryk Heisig <hyniu@o2.pl>
+PKG_CPE_ID:=cpe:/a:google:android_debug_bridge
+
+include $(INCLUDE_DIR)/package.mk
+
+ifeq ($(CONFIG_BIG_ENDIAN),y)
+TARGET_CFLAGS+= -DHAVE_BIG_ENDIAN=1
+endif
+TARGET_CFLAGS+= -D_GNU_SOURCE
+
+define Package/adb
+  SECTION:=utils
+  CATEGORY:=Utilities
+  TITLE:=Android Debug Bridge CLI tool
+  URL:=http://tools.android.com/
+  DEPENDS:=+zlib +libopenssl +libpthread
+endef
+
+define Package/adb/description
+ Android Debug Bridge (adb) is a versatile command line tool that lets you communicate with an emulator instance or connected Android-powered device.
+endef
+
+# Nothing just to be sure
+#define Build/Configure
+#endef
+
+define Build/Compile
+	$(MAKE) -C $(PKG_BUILD_DIR)/adb/ \
+		$(TARGET_CONFIGURE_OPTS) \
+		TARGET=Linux \
+		CFLAGS="$(TARGET_CFLAGS) $(TARGET_CPPFLAGS)" \
+		LDFLAGS="$(TARGET_LDFLAGS)"
+endef
+
+define Package/adb/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/adb/adb $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,adb))
diff --git a/package/utils/adb/patches/001-create_Makefile.patch b/package/utils/adb/patches/001-create_Makefile.patch
new file mode 100644
index 0000000..d7fa00c
--- /dev/null
+++ b/package/utils/adb/patches/001-create_Makefile.patch
@@ -0,0 +1,45 @@
+--- /dev/null
++++ b/adb/Makefile
+@@ -0,0 +1,42 @@
++SRCS+= adb.c
++SRCS+= adb_auth_host.c
++SRCS+= adb_client.c
++SRCS+= commandline.c
++SRCS+= console.c
++SRCS+= fdevent.c
++SRCS+= file_sync_client.c
++SRCS+= get_my_path_linux.c
++SRCS+= services.c
++SRCS+= sockets.c
++SRCS+= transport.c
++SRCS+= transport_local.c
++SRCS+= transport_usb.c
++SRCS+= usb_linux.c
++
++VPATH+= ../libcutils
++SRCS+= load_file.c
++SRCS+= socket_inaddr_any_server.c
++SRCS+= socket_local_client.c
++SRCS+= socket_local_server.c
++SRCS+= socket_loopback_client.c
++SRCS+= socket_loopback_server.c
++SRCS+= socket_network_client.c
++
++VPATH+= ../libzipfile
++SRCS+= centraldir.c
++SRCS+= zipfile.c
++
++CPPFLAGS+= -DADB_HOST=1
++CPPFLAGS+= -DHAVE_FORKEXEC=1
++CPPFLAGS+= -I.
++CPPFLAGS+= -I../include
++CPPFLAGS+= -D_FILE_OFFSET_BITS=64
++
++LIBS+= -lcrypto -lpthread -lz
++
++OBJS= $(SRCS:.c=.o)
++
++all: adb
++
++adb: $(OBJS)
++	$(CC) -o $@ $(LDFLAGS) $(OBJS) $(LIBS)
diff --git a/package/utils/adb/patches/003-fix-musl-build.patch b/package/utils/adb/patches/003-fix-musl-build.patch
new file mode 100644
index 0000000..8a974b1
--- /dev/null
+++ b/package/utils/adb/patches/003-fix-musl-build.patch
@@ -0,0 +1,10 @@
+--- a/adb/usb_linux.c
++++ b/adb/usb_linux.c
+@@ -21,6 +21,7 @@
+ 
+ #include <sys/ioctl.h>
+ #include <sys/types.h>
++#include <sys/sysmacros.h>
+ #include <sys/time.h>
+ #include <dirent.h>
+ #include <fcntl.h>
diff --git a/package/utils/adb/patches/010-openssl-1.1.patch b/package/utils/adb/patches/010-openssl-1.1.patch
new file mode 100644
index 0000000..e4df372
--- /dev/null
+++ b/package/utils/adb/patches/010-openssl-1.1.patch
@@ -0,0 +1,28 @@
+--- a/adb/adb_auth_host.c
++++ b/adb/adb_auth_host.c
+@@ -83,7 +83,13 @@ static int RSA_to_RSAPublicKey(RSA *rsa,
+     }
+ 
+     BN_set_bit(r32, 32);
++#if OPENSSL_VERSION_NUMBER >= 0x10100000L
++    const BIGNUM *rsa_n, *rsa_e;
++    RSA_get0_key(rsa, &rsa_n, &rsa_e, NULL);
++    BN_copy(n, rsa_n);
++#else
+     BN_copy(n, rsa->n);
++#endif
+     BN_set_bit(r, RSANUMWORDS * 32);
+     BN_mod_sqr(rr, r, n, ctx);
+     BN_div(NULL, rem, n, r32, ctx);
+@@ -97,7 +103,11 @@ static int RSA_to_RSAPublicKey(RSA *rsa,
+         BN_div(n, rem, n, r32, ctx);
+         pkey->n[i] = BN_get_word(rem);
+     }
++#if OPENSSL_VERSION_NUMBER >= 0x10100000L
++    pkey->exponent = BN_get_word(rsa_e);
++#else
+     pkey->exponent = BN_get_word(rsa->e);
++#endif
+ 
+ out:
+     BN_free(n0inv);
diff --git a/package/utils/adb/patches/020-cherry-picked-superspeed-fix.patch b/package/utils/adb/patches/020-cherry-picked-superspeed-fix.patch
new file mode 100644
index 0000000..4dbcc58
--- /dev/null
+++ b/package/utils/adb/patches/020-cherry-picked-superspeed-fix.patch
@@ -0,0 +1,39 @@
+From 58b01e01875e2f6ae593ded197430bc23713dd0a Mon Sep 17 00:00:00 2001
+From: Ingo Rohloff <lundril@gmx.de>
+Date: Fri, 16 May 2014 21:51:41 +0200
+Subject: [PATCH] ADB on linux: Handle USB SuperSpeed extra Descriptors
+
+Under Linux, ADB manually parses USB Descriptors to check for
+possible ADB USB Interfaces. USB Devices connected with SuperSpeed
+will exhibit extra USB SuperSpeed Endpoint Companion Descriptors.
+This patch handles these USB SuperSpeed specific USB Descriptors.
+
+Change-Id: Icd1e5fdde0b324c7df4f933583499f2c52a922f3
+Signed-off-by: Ingo Rohloff <lundril@gmx.de>
+---
+ adb/usb_linux.c | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+--- a/adb/usb_linux.c
++++ b/adb/usb_linux.c
+@@ -238,8 +238,20 @@ static void find_usb_device(const char *
+                             // looks like ADB...
+                         ep1 = (struct usb_endpoint_descriptor *)bufptr;
+                         bufptr += USB_DT_ENDPOINT_SIZE;
++                            // For USB 3.0 SuperSpeed devices, skip potential
++                            // USB 3.0 SuperSpeed Endpoint Companion descriptor
++                        if (bufptr+2 <= devdesc + desclength &&
++                            bufptr[0] == USB_DT_SS_EP_COMP_SIZE &&
++                            bufptr[1] == USB_DT_SS_ENDPOINT_COMP) {
++                            bufptr += USB_DT_SS_EP_COMP_SIZE;
++                        }
+                         ep2 = (struct usb_endpoint_descriptor *)bufptr;
+                         bufptr += USB_DT_ENDPOINT_SIZE;
++                        if (bufptr+2 <= devdesc + desclength &&
++                            bufptr[0] == USB_DT_SS_EP_COMP_SIZE &&
++                            bufptr[1] == USB_DT_SS_ENDPOINT_COMP) {
++                            bufptr += USB_DT_SS_EP_COMP_SIZE;
++                        }
+ 
+                         if (bufptr > devdesc + desclength ||
+                             ep1->bLength != USB_DT_ENDPOINT_SIZE ||
diff --git a/package/utils/adbd/Makefile b/package/utils/adbd/Makefile
new file mode 100644
index 0000000..260b058
--- /dev/null
+++ b/package/utils/adbd/Makefile
@@ -0,0 +1,66 @@
+include $(TOPDIR)/rules.mk
+#Based on adb package from AUR https://aur.archlinux.org/packages/adb/ , reused Makefile
+
+PKG_NAME:=adbd
+PKG_VERSION:=android.5.0.2_r1
+PKG_RELEASE:=1
+
+USE_SOURCE_DIR:=$(CURDIR)/src
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
+
+include $(INCLUDE_DIR)/package.mk
+
+ifeq ($(CONFIG_BIG_ENDIAN),y)
+TARGET_CFLAGS+= -DHAVE_BIG_ENDIAN=1
+endif
+TARGET_CFLAGS+= -D_GNU_SOURCE
+
+ifeq ($(CONFIG_TARGET_mmp_asr1901_KSTR901),y)
+TARGET_CFLAGS+= -DANDROID_SMP
+endif
+
+ifeq ($(CONFIG_TARGET_mmp_asr1901_KSTR906),y)
+TARGET_CFLAGS+= -DANDROID_SMP
+endif
+
+define Package/adbd
+  SECTION:=utils
+  CATEGORY:=Utilities
+  TITLE:=Android Debug Bridge CLI tool
+  URL:=http://tools.android.com/
+  DEPENDS:=+zlib +libpthread +liblog +libmbedtls
+endef
+
+define Package/bridge/description
+ Android Debug Bridge (adb) is a versatile command line tool that lets you communicate with an emulator instance or connected Android-powered device.
+endef
+
+define Build/Clean
+if [ -d $(PKG_BUILD_DIR) ]; then \
+	cd $(PKG_BUILD_DIR); \
+	rm -rf .built .configured_ .prepared .quilt_checked .source_dir ipkg-*; \
+	rm -f src/adbd/adbd; \
+	$(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR)/adb \
+		CROSS_COMPILE="$(TARGET_CROSS)" \
+		clean; \
+fi
+endef
+
+define Build/Compile
+	rm -rf $(PKG_BUILD_DIR)/adb/adbd
+	$(MAKE) -C $(PKG_BUILD_DIR)/adb/ \
+		$(TARGET_CONFIGURE_OPTS) \
+		TARGET=Linux \
+		CFLAGS="$(TARGET_CFLAGS) $(TARGET_CPPFLAGS)" \
+		LDFLAGS="$(TARGET_LDFLAGS)" \
+		all
+endef
+
+define Package/adbd/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(INSTALL_DIR) $(1)/etc/init.d/
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/adb/adbd $(1)/usr/bin/
+	$(INSTALL_BIN) ./adbd.init $(1)/etc/init.d/adbd
+endef
+
+$(eval $(call BuildPackage,adbd))
diff --git a/package/utils/adbd/adbd.init b/package/utils/adbd/adbd.init
new file mode 100644
index 0000000..54d8dbb
--- /dev/null
+++ b/package/utils/adbd/adbd.init
@@ -0,0 +1,20 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2006-2011 OpenWrt.org
+
+START=80
+STOP=99
+
+USE_PROCD=1
+PROG=/usr/bin/adbd
+OOM_ADJ=-17
+
+start_service() {
+        procd_open_instance
+        procd_set_param oom_score_adj $OOM_ADJ
+        procd_set_param command $PROG -D
+        procd_close_instance
+}
+
+shutdown() {
+        echo shutdown
+}
diff --git a/package/utils/adbd/src/.gitignore b/package/utils/adbd/src/.gitignore
new file mode 100644
index 0000000..d39e11c
--- /dev/null
+++ b/package/utils/adbd/src/.gitignore
@@ -0,0 +1,8 @@
+.built
+.configured_
+.prepared
+.quilt_checked
+.source_dir
+/adb/adbd
+/ipkg-pxa1826/
+
diff --git a/package/utils/adbd/src/adb/Android.mk b/package/utils/adbd/src/adb/Android.mk
new file mode 100644
index 0000000..818bedb
--- /dev/null
+++ b/package/utils/adbd/src/adb/Android.mk
@@ -0,0 +1,174 @@
+# Copyright 2005 The Android Open Source Project
+#
+# Android.mk for adb
+#
+
+LOCAL_PATH:= $(call my-dir)
+
+# adb host tool
+# =========================================================
+include $(CLEAR_VARS)
+
+# Default to a virtual (sockets) usb interface
+USB_SRCS :=
+EXTRA_SRCS :=
+
+ifeq ($(HOST_OS),linux)
+  USB_SRCS := usb_linux.c
+  EXTRA_SRCS := get_my_path_linux.c
+  LOCAL_LDLIBS += -lrt -ldl -lpthread
+  LOCAL_CFLAGS += -DWORKAROUND_BUG6558362
+endif
+
+ifeq ($(HOST_OS),darwin)
+  USB_SRCS := usb_osx.c
+  EXTRA_SRCS := get_my_path_darwin.c
+  LOCAL_LDLIBS += -lpthread -framework CoreFoundation -framework IOKit -framework Carbon
+endif
+
+ifeq ($(HOST_OS),freebsd)
+  USB_SRCS := usb_libusb.c
+  EXTRA_SRCS := get_my_path_freebsd.c
+  LOCAL_LDLIBS += -lpthread -lusb
+endif
+
+ifeq ($(HOST_OS),windows)
+  USB_SRCS := usb_windows.c
+  EXTRA_SRCS := get_my_path_windows.c
+  EXTRA_STATIC_LIBS := AdbWinApi
+  ifneq ($(strip $(USE_CYGWIN)),)
+    # Pure cygwin case
+    LOCAL_LDLIBS += -lpthread -lgdi32
+    LOCAL_C_INCLUDES += /usr/include/w32api/ddk
+  endif
+  ifneq ($(strip $(USE_MINGW)),)
+    # MinGW under Linux case
+    LOCAL_LDLIBS += -lws2_32 -lgdi32
+    USE_SYSDEPS_WIN32 := 1
+    LOCAL_C_INCLUDES += /usr/i586-mingw32msvc/include/ddk
+  endif
+  LOCAL_C_INCLUDES += development/host/windows/usb/api/
+endif
+
+LOCAL_SRC_FILES := \
+	adb.c \
+	console.c \
+	transport.c \
+	transport_local.c \
+	transport_usb.c \
+	commandline.c \
+	adb_client.c \
+	adb_auth_host.c \
+	sockets.c \
+	services.c \
+	file_sync_client.c \
+	$(EXTRA_SRCS) \
+	$(USB_SRCS) \
+	usb_vendors.c
+
+LOCAL_C_INCLUDES += external/openssl/include
+
+ifneq ($(USE_SYSDEPS_WIN32),)
+  LOCAL_SRC_FILES += sysdeps_win32.c
+else
+  LOCAL_SRC_FILES += fdevent.c
+endif
+
+LOCAL_CFLAGS += -O2 -g -DADB_HOST=1 -Wall -Wno-unused-parameter -Werror
+LOCAL_CFLAGS += -D_XOPEN_SOURCE -D_GNU_SOURCE
+LOCAL_MODULE := adb
+LOCAL_MODULE_TAGS := debug
+
+LOCAL_STATIC_LIBRARIES := libzipfile libunz $(EXTRA_STATIC_LIBS)
+ifeq ($(USE_SYSDEPS_WIN32),)
+	LOCAL_STATIC_LIBRARIES += libcutils
+endif
+
+include $(BUILD_HOST_EXECUTABLE)
+
+$(call dist-for-goals,dist_files sdk,$(LOCAL_BUILT_MODULE))
+
+ifeq ($(HOST_OS),windows)
+$(LOCAL_INSTALLED_MODULE): \
+    $(HOST_OUT_EXECUTABLES)/AdbWinApi.dll \
+    $(HOST_OUT_EXECUTABLES)/AdbWinUsbApi.dll
+endif
+
+
+# adbd device daemon
+# =========================================================
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+	adb.c \
+	fdevent.c \
+	transport.c \
+	transport_local.c \
+	transport_usb.c \
+	adb_auth_client.c \
+	sockets.c \
+	services.c \
+	file_sync_service.c \
+	jdwp_service.c \
+	framebuffer_service.c \
+	remount_service.c \
+	usb_linux_client.c
+
+LOCAL_CFLAGS := -O2 -g -DADB_HOST=0 -Wall -Wno-unused-parameter -Werror
+LOCAL_CFLAGS += -D_XOPEN_SOURCE -D_GNU_SOURCE
+
+ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
+LOCAL_CFLAGS += -DALLOW_ADBD_ROOT=1
+endif
+
+LOCAL_MODULE := adbd
+
+LOCAL_FORCE_STATIC_EXECUTABLE := true
+LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT_SBIN)
+LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_SBIN_UNSTRIPPED)
+
+LOCAL_STATIC_LIBRARIES := liblog libcutils libc libselinux
+include $(BUILD_EXECUTABLE)
+
+
+# adb host tool for device-as-host
+# =========================================================
+ifneq ($(SDK_ONLY),true)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+	adb.c \
+	console.c \
+	transport.c \
+	transport_local.c \
+	transport_usb.c \
+	commandline.c \
+	adb_client.c \
+	adb_auth_host.c \
+	sockets.c \
+	services.c \
+	file_sync_client.c \
+	get_my_path_linux.c \
+	usb_linux.c \
+	usb_vendors.c \
+	fdevent.c
+
+LOCAL_CFLAGS := \
+	-O2 \
+	-g \
+	-DADB_HOST=1 \
+	-DADB_HOST_ON_TARGET=1 \
+	-Wall -Wno-unused-parameter -Werror \
+	-D_XOPEN_SOURCE \
+	-D_GNU_SOURCE
+
+#LOCAL_C_INCLUDES += external/openssl/include
+
+LOCAL_MODULE := adb
+
+LOCAL_STATIC_LIBRARIES := libzipfile libunz libcutils
+
+
+include $(BUILD_EXECUTABLE)
+endif
diff --git a/package/utils/adbd/src/adb/MODULE_LICENSE_APACHE2 b/package/utils/adbd/src/adb/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/package/utils/adbd/src/adb/MODULE_LICENSE_APACHE2
diff --git a/package/utils/adbd/src/adb/Makefile b/package/utils/adbd/src/adb/Makefile
new file mode 100644
index 0000000..1a2e0a3
--- /dev/null
+++ b/package/utils/adbd/src/adb/Makefile
@@ -0,0 +1,56 @@
+
+SRCS := \
+	adb.c \
+	fdevent.c \
+	transport.c \
+	transport_local.c \
+	transport_usb.c \
+	adb_auth_client.c \
+	sockets.c \
+	services.c \
+	file_sync_service.c \
+	jdwp_service.c \
+	framebuffer_service.c \
+	remount_service.c \
+	usb_linux_client.c \
+	b64_pton.c \
+	rsa.c \
+	sha256.c \
+	sha.c
+
+VPATH+= ../libcutils
+SRCS+= load_file.c
+SRCS+= socket_inaddr_any_server.c
+SRCS+= socket_local_client.c
+SRCS+= socket_local_server.c
+SRCS+= socket_loopback_client.c
+SRCS+= socket_loopback_server.c
+SRCS+= socket_network_client.c
+SRCS+= properties.c
+
+CPPFLAGS += \
+	-O2 \
+	-g \
+	-DADB_HOST=0 \
+	-D_XOPEN_SOURCE \
+	-D_GNU_SOURCE \
+	-Wall -Wno-unused-parameter -Werror -Wno-deprecated-declarations
+
+CPPFLAGS+= -DALLOW_ADBD_ROOT=1
+CPPFLAGS+= -DHAVE_FORKEXEC=1
+CPPFLAGS+= -D_FILE_OFFSET_BITS=64
+CPPFLAGS+= -I. -I../include
+
+LIBS+= -lpthread -lz -llog
+
+LIBS+= -lmbedtls
+
+OBJS= $(SRCS:.c=.o)
+
+all: adbd
+
+adbd: $(OBJS)
+	$(CC) -o $@ $(LDFLAGS) $(OBJS) $(LIBS)
+
+clean:
+	rm -rf *.o adbd
diff --git a/package/utils/adbd/src/adb/NOTICE b/package/utils/adbd/src/adb/NOTICE
new file mode 100644
index 0000000..9ffcc08
--- /dev/null
+++ b/package/utils/adbd/src/adb/NOTICE
@@ -0,0 +1,191 @@
+
+   Copyright (c) 2006-2009, The Android Open Source Project
+   Copyright 2006, Brian Swetland <swetland@frotz.net>
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+
+   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.
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
diff --git a/package/utils/adbd/src/adb/OVERVIEW.TXT b/package/utils/adbd/src/adb/OVERVIEW.TXT
new file mode 100644
index 0000000..c40695a
--- /dev/null
+++ b/package/utils/adbd/src/adb/OVERVIEW.TXT
@@ -0,0 +1,139 @@
+Implementation notes regarding ADB.
+
+I. General Overview:
+
+The Android Debug Bridge (ADB) is used to:
+
+- keep track of all Android devices and emulators instances
+  connected to or running on a given host developer machine
+
+- implement various control commands (e.g. "adb shell", "adb pull", etc..)
+  for the benefit of clients (command-line users, or helper programs like
+  DDMS). These commands are what is called a 'service' in ADB.
+
+As a whole, everything works through the following components:
+
+  1. The ADB server
+
+    This is a background process that runs on the host machine. Its purpose
+    if to sense the USB ports to know when devices are attached/removed,
+    as well as when emulator instances start/stop.
+
+    It thus maintains a list of "connected devices" and assigns a 'state'
+    to each one of them: OFFLINE, BOOTLOADER, RECOVERY or ONLINE (more on
+    this below).
+
+    The ADB server is really one giant multiplexing loop whose purpose is
+    to orchestrate the exchange of data (packets, really) between clients,
+    services and devices.
+
+
+  2. The ADB daemon (adbd)
+
+    The 'adbd' program runs as a background process within an Android device
+    or emulated system. Its purpose is to connect to the ADB server
+    (through USB for devices, through TCP for emulators) and provide a
+    few services for clients that run on the host.
+
+    The ADB server considers that a device is ONLINE when it has successfully
+    connected to the adbd program within it. Otherwise, the device is OFFLINE,
+    meaning that the ADB server detected a new device/emulator, but could not
+    connect to the adbd daemon.
+
+    the BOOTLOADER and RECOVERY states correspond to alternate states of
+    devices when they are in the bootloader or recovery mode.
+
+  3. The ADB command-line client
+
+    The 'adb' command-line program is used to run adb commands from a shell
+    or a script. It first tries to locate the ADB server on the host machine,
+    and will start one automatically if none is found.
+
+    then, the client sends its service requests to the ADB server. It doesn't
+    need to know.
+
+    Currently, a single 'adb' binary is used for both the server and client.
+    this makes distribution and starting the server easier.
+
+
+  4. Services
+
+    There are essentially two kinds of services that a client can talk to.
+
+    Host Services:
+      these services run within the ADB Server and thus do not need to
+      communicate with a device at all. A typical example is "adb devices"
+      which is used to return the list of currently known devices and their
+      state. They are a few couple other services though.
+
+    Local Services:
+      these services either run within the adbd daemon, or are started by
+      it on the device. The ADB server is used to multiplex streams
+      between the client and the service running in adbd. In this case
+      its role is to initiate the connection, then of being a pass-through
+      for the data.
+
+
+II. Protocol details:
+
+  1. Client <-> Server protocol:
+
+    This details the protocol used between ADB clients and the ADB
+    server itself. The ADB server listens on TCP:localhost:5037.
+
+    A client sends a request using the following format:
+
+        1. A 4-byte hexadecimal string giving the length of the payload
+        2. Followed by the payload itself.
+
+    For example, to query the ADB server for its internal version number,
+    the client will do the following:
+
+        1. Connect to tcp:localhost:5037
+        2. Send the string "000Chost:version" to the corresponding socket
+
+    The 'host:' prefix is used to indicate that the request is addressed
+    to the server itself (we will talk about other kinds of requests later).
+    The content length is encoded in ASCII for easier debugging.
+
+    The server should answer a request with one of the following:
+
+        1. For success, the 4-byte "OKAY" string
+
+        2. For failure, the 4-byte "FAIL" string, followed by a
+           4-byte hex length, followed by a string giving the reason
+           for failure.
+
+        3. As a special exception, for 'host:version', a 4-byte
+           hex string corresponding to the server's internal version number
+
+    Note that the connection is still alive after an OKAY, which allows the
+    client to make other requests. But in certain cases, an OKAY will even
+    change the state of the connection. 
+
+    For example, the case of the 'host:transport:<serialnumber>' request,
+    where '<serialnumber>' is used to identify a given device/emulator; after
+    the "OKAY" answer, all further requests made by the client will go
+    directly to the corresponding adbd daemon.
+
+    The file SERVICES.TXT lists all services currently implemented by ADB.
+
+
+  2. Transports:
+
+    An ADB transport models a connection between the ADB server and one device
+    or emulator. There are currently two kinds of transports:
+
+       - USB transports, for physical devices through USB
+
+       - Local transports, for emulators running on the host, connected to
+         the server through TCP
+
+    In theory, it should be possible to write a local transport that proxies
+    a connection between an ADB server and a device/emulator connected to/
+    running on another machine. This hasn't been done yet though.
+
+    Each transport can carry one or more multiplexed streams between clients
+    and the device/emulator they point to. The ADB server must handle
+    unexpected transport disconnections (e.g. when a device is physically
+    unplugged) properly.
diff --git a/package/utils/adbd/src/adb/SERVICES.TXT b/package/utils/adbd/src/adb/SERVICES.TXT
new file mode 100644
index 0000000..63000f2
--- /dev/null
+++ b/package/utils/adbd/src/adb/SERVICES.TXT
@@ -0,0 +1,259 @@
+This file tries to document all requests a client can make
+to the ADB server of an adbd daemon. See the OVERVIEW.TXT document
+to understand what's going on here.
+
+HOST SERVICES:
+
+host:version
+    Ask the ADB server for its internal version number.
+
+    As a special exception, the server will respond with a 4-byte
+    hex string corresponding to its internal version number, without
+    any OKAY or FAIL.
+
+host:kill
+    Ask the ADB server to quit immediately. This is used when the
+    ADB client detects that an obsolete server is running after an
+    upgrade.
+
+host:devices
+host:devices-l
+    Ask to return the list of available Android devices and their
+    state. devices-l includes the device paths in the state.
+    After the OKAY, this is followed by a 4-byte hex len,
+    and a string that will be dumped as-is by the client, then
+    the connection is closed
+
+host:track-devices
+    This is a variant of host:devices which doesn't close the
+    connection. Instead, a new device list description is sent
+    each time a device is added/removed or the state of a given
+    device changes (hex4 + content). This allows tools like DDMS
+    to track the state of connected devices in real-time without
+    polling the server repeatedly.
+
+host:emulator:<port>
+    This is a special query that is sent to the ADB server when a
+    new emulator starts up. <port> is a decimal number corresponding
+    to the emulator's ADB control port, i.e. the TCP port that the
+    emulator will forward automatically to the adbd daemon running
+    in the emulator system.
+
+    This mechanism allows the ADB server to know when new emulator
+    instances start.
+
+host:transport:<serial-number>
+    Ask to switch the connection to the device/emulator identified by
+    <serial-number>. After the OKAY response, every client request will
+    be sent directly to the adbd daemon running on the device.
+    (Used to implement the -s option)
+
+host:transport-usb
+    Ask to switch the connection to one device connected through USB
+    to the host machine. This will fail if there are more than one such
+    devices. (Used to implement the -d convenience option)
+
+host:transport-local
+    Ask to switch the connection to one emulator connected through TCP.
+    This will fail if there is more than one such emulator instance
+    running. (Used to implement the -e convenience option)
+
+host:transport-any
+    Another host:transport variant. Ask to switch the connection to
+    either the device or emulator connect to/running on the host.
+    Will fail if there is more than one such device/emulator available.
+    (Used when neither -s, -d or -e are provided)
+
+host-serial:<serial-number>:<request>
+    This is a special form of query, where the 'host-serial:<serial-number>:'
+    prefix can be used to indicate that the client is asking the ADB server
+    for information related to a specific device. <request> can be in one
+    of the format described below.
+
+host-usb:<request>
+    A variant of host-serial used to target the single USB device connected
+    to the host. This will fail if there is none or more than one.
+
+host-local:<request>
+    A variant of host-serial used to target the single emulator instance
+    running on the host. This will fail if there is none or more than one.
+
+host:<request>
+    When asking for information related to a device, 'host:' can also be
+    interpreted as 'any single device or emulator connected to/running on
+    the host'.
+
+<host-prefix>:get-product
+    XXX
+
+<host-prefix>:get-serialno
+    Returns the serial number of the corresponding device/emulator.
+    Note that emulator serial numbers are of the form "emulator-5554"
+
+<host-prefix>:get-devpath
+    Returns the device path of the corresponding device/emulator.
+
+<host-prefix>:get-state
+    Returns the state of a given device as a string.
+
+<host-prefix>:forward:<local>;<remote>
+    Asks the ADB server to forward local connections from <local>
+    to the <remote> address on a given device.
+
+    There, <host-prefix> can be one of the
+    host-serial/host-usb/host-local/host prefixes as described previously
+    and indicates which device/emulator to target.
+
+    the format of <local> is one of:
+
+        tcp:<port>      -> TCP connection on localhost:<port>
+        local:<path>    -> Unix local domain socket on <path>
+
+    the format of <remote> is one of:
+
+        tcp:<port>      -> TCP localhost:<port> on device
+        local:<path>    -> Unix local domain socket on device
+        jdwp:<pid>      -> JDWP thread on VM process <pid>
+
+    or even any one of the local services described below.
+
+<host-prefix>:forward:norebind:<local>;<remote>
+    Same as <host-prefix>:forward:<local>;<remote> except that it will
+    fail it there is already a forward connection from <local>.
+
+    Used to implement 'adb forward --no-rebind <local> <remote>'
+
+<host-prefix>:killforward:<local>
+    Remove any existing forward local connection from <local>.
+    This is used to implement 'adb forward --remove <local>'
+
+<host-prefix>:killforward-all
+    Remove all forward network connections.
+    This is used to implement 'adb forward --remove-all'.
+
+<host-prefix>:list-forward
+    List all existing forward connections from this server.
+    This returns something that looks like the following:
+
+       <hex4>: The length of the payload, as 4 hexadecimal chars.
+       <payload>: A series of lines of the following format:
+
+         <serial> " " <local> " " <remote> "\n"
+
+    Where <serial> is a device serial number.
+          <local>  is the host-specific endpoint (e.g. tcp:9000).
+          <remote> is the device-specific endpoint.
+
+    Used to implement 'adb forward --list'.
+
+LOCAL SERVICES:
+
+All the queries below assumed that you already switched the transport
+to a real device, or that you have used a query prefix as described
+above.
+
+shell:command arg1 arg2 ...
+    Run 'command arg1 arg2 ...' in a shell on the device, and return
+    its output and error streams. Note that arguments must be separated
+    by spaces. If an argument contains a space, it must be quoted with
+    double-quotes. Arguments cannot contain double quotes or things
+    will go very wrong.
+
+    Note that this is the non-interactive version of "adb shell"
+
+shell:
+    Start an interactive shell session on the device. Redirect
+    stdin/stdout/stderr as appropriate. Note that the ADB server uses
+    this to implement "adb shell", but will also cook the input before
+    sending it to the device (see interactive_shell() in commandline.c)
+
+remount:
+    Ask adbd to remount the device's filesystem in read-write mode,
+    instead of read-only. This is usually necessary before performing
+    an "adb sync" or "adb push" request.
+
+    This request may not succeed on certain builds which do not allow
+    that.
+
+dev:<path>
+    Opens a device file and connects the client directly to it for
+    read/write purposes. Useful for debugging, but may require special
+    privileges and thus may not run on all devices. <path> is a full
+    path from the root of the filesystem.
+
+tcp:<port>
+    Tries to connect to tcp port <port> on localhost.
+
+tcp:<port>:<server-name>
+    Tries to connect to tcp port <port> on machine <server-name> from
+    the device. This can be useful to debug some networking/proxy
+    issues that can only be revealed on the device itself.
+
+local:<path>
+    Tries to connect to a Unix domain socket <path> on the device
+
+localreserved:<path>
+localabstract:<path>
+localfilesystem:<path>
+    Variants of local:<path> that are used to access other Android
+    socket namespaces.
+
+framebuffer:
+    This service is used to send snapshots of the framebuffer to a client.
+    It requires sufficient privileges but works as follow:
+
+      After the OKAY, the service sends 16-byte binary structure
+      containing the following fields (little-endian format):
+
+            depth:   uint32_t:    framebuffer depth
+            size:    uint32_t:    framebuffer size in bytes
+            width:   uint32_t:    framebuffer width in pixels
+            height:  uint32_t:    framebuffer height in pixels
+
+      With the current implementation, depth is always 16, and
+      size is always width*height*2
+
+      Then, each time the client wants a snapshot, it should send
+      one byte through the channel, which will trigger the service
+      to send it 'size' bytes of framebuffer data.
+
+      If the adbd daemon doesn't have sufficient privileges to open
+      the framebuffer device, the connection is simply closed immediately.
+
+jdwp:<pid>
+    Connects to the JDWP thread running in the VM of process <pid>.
+
+track-jdwp
+    This is used to send the list of JDWP pids periodically to the client.
+    The format of the returned data is the following:
+
+        <hex4>:    the length of all content as a 4-char hexadecimal string
+        <content>: a series of ASCII lines of the following format:
+                        <pid> "\n"
+
+    This service is used by DDMS to know which debuggable processes are running
+    on the device/emulator.
+
+    Note that there is no single-shot service to retrieve the list only once.
+
+sync:
+    This starts the file synchronisation service, used to implement "adb push"
+    and "adb pull". Since this service is pretty complex, it will be detailed
+    in a companion document named SYNC.TXT
+
+reverse:<forward-command>
+    This implements the 'adb reverse' feature, i.e. the ability to reverse
+    socket connections from a device to the host. <forward-command> is one
+    of the forwarding commands that are described above, as in:
+
+      list-forward
+      forward:<local>;<remote>
+      forward:norebind:<local>;<remote>
+      killforward-all
+      killforward:<local>
+
+    Note that in this case, <local> corresponds to the socket on the device
+    and <remote> corresponds to the socket on the host.
+
+    The output of reverse:list-forward is the same as host:list-forward
+    except that <serial> will be just 'host'.
diff --git a/package/utils/adbd/src/adb/SYNC.TXT b/package/utils/adbd/src/adb/SYNC.TXT
new file mode 100644
index 0000000..e74d217
--- /dev/null
+++ b/package/utils/adbd/src/adb/SYNC.TXT
@@ -0,0 +1,84 @@
+This file tries to document file related requests a client can make
+to the ADB server of an adbd daemon. See the OVERVIEW.TXT document
+to understand what's going on here. See the SERVICES.TXT to learn more
+about the other requests that are possible.
+
+SYNC SERVICES:
+
+
+Requesting the sync service ("sync:") using the protocol as described in
+SERVICES.TXT sets the connection in sync mode. This mode is a binary mode that
+differ from the regular adb protocol. The connection stays in sync mode until
+explicitly terminated (see below).
+
+After the initial "sync:" command is sent the server must respond with either
+"OKAY" or "FAIL" as per usual. 
+
+In sync mode both the server and the client will frequently use eight-byte
+packets to communicate in this document called sync request and sync
+responses. The first four bytes is an id and specifies sync request is
+represented by four utf-8 characters. The last four bytes is a Little-Endian
+integer, with various uses. This number will be called "length" below. In fact
+all binary integers are Little-Endian in the sync mode. Sync mode is
+implicitly exited after each sync request, and normal adb communication
+follows as described in SERVICES.TXT.
+
+The following sync requests are accepted:
+LIST - List the files in a folder
+SEND - Send a file to device
+RECV - Retreive a file from device
+
+Not yet documented:
+STAT - Stat a file
+ULNK - Unlink (remove) a file. (Not currently supported)
+
+For all of the sync request above the must be followed by length number of
+bytes containing an utf-8 string with a remote filename.
+
+LIST:
+Lists files in the directory specified by the remote filename. The server will
+respond with zero or more directory entries or "dents".
+
+The directory entries will be returned in the following form
+1. A four-byte sync response id beeing "DENT"
+2. A four-byte integer representing file mode.
+3. A four-byte integer representing file size.
+4. A four-byte integer representing last modified time.
+5. A four-byte integer representing file name length.
+6. length number of bytes containing an utf-8 string representing the file
+   name.
+
+When an sync response "DONE" is received the listing is done.
+
+SEND:
+The remote file name is split into two parts separated by the last
+comma (","). The first part is the actual path, while the second is a decimal
+encoded file mode containing the permissions of the file on device.
+
+Note that some file types will be deleted before the copying starts, and if
+the transfer fails. Some file types will not be deleted, which allows
+  adb push disk_image /some_block_device
+to work.
+
+After this the actual file is sent in chunks. Each chucks has the following
+format.
+A sync request with id "DATA" and length equal to the chunk size. After
+follows chunk size number of bytes. This is repeated until the file is
+transfered. Each chunk must not be larger than 64k.
+
+When the file is tranfered a sync request "DONE" is sent, where length is set
+to the last modified time for the file. The server responds to this last
+request (but not to chuck requests) with an "OKAY" sync response (length can
+be ignored).
+
+
+RECV:
+Retrieves a file from device to a local file. The remote path is the path to
+the file that will be returned. Just as for the SEND sync request the file
+received is split up into chunks. The sync response id is "DATA" and length is
+the chuck size. After follows chunk size number of bytes. This is repeated
+until the file is transfered. Each chuck will not be larger than 64k.
+
+When the file is transfered a sync resopnse "DONE" is retrieved where the
+length can be ignored.
+
diff --git a/package/utils/adbd/src/adb/adb.c b/package/utils/adbd/src/adb/adb.c
new file mode 100644
index 0000000..8368ad4
--- /dev/null
+++ b/package/utils/adbd/src/adb/adb.c
@@ -0,0 +1,1730 @@
+/*
+ * 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.
+ */
+
+#define  TRACE_TAG   TRACE_ADB
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <stddef.h>
+#include <string.h>
+#include <time.h>
+#include <sys/time.h>
+#include <stdint.h>
+#include <grp.h> // changed by feilv
+
+#include "sysdeps.h"
+#include "adb.h"
+#include "adb_auth.h"
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+
+#if !ADB_HOST
+#include <cutils/properties.h>
+#include <private/android_filesystem_config.h>
+// changed by feilv
+#include <linux/capability.h>
+#include <sys/prctl.h>
+#include <sys/mount.h>
+//#include <getopt.h>
+//#include <selinux/selinux.h>
+#else
+#include "usb_vendors.h"
+#endif
+
+#if ADB_TRACE
+ADB_MUTEX_DEFINE( D_lock );
+#endif
+
+int HOST = 0;
+int gListenAll = 0;
+
+static int auth_enabled = 0;
+
+#if !ADB_HOST
+static const char *adb_device_banner = "device";
+// changed by feilv
+//static const char *root_seclabel = NULL;
+#endif
+
+void fatal(const char *fmt, ...)
+{
+    va_list ap;
+    va_start(ap, fmt);
+    fprintf(stderr, "error: ");
+    vfprintf(stderr, fmt, ap);
+    fprintf(stderr, "\n");
+    va_end(ap);
+    exit(-1);
+}
+
+void fatal_errno(const char *fmt, ...)
+{
+    va_list ap;
+    va_start(ap, fmt);
+    fprintf(stderr, "error: %s: ", strerror(errno));
+    vfprintf(stderr, fmt, ap);
+    fprintf(stderr, "\n");
+    va_end(ap);
+    exit(-1);
+}
+
+int   adb_trace_mask;
+
+/* read a comma/space/colum/semi-column separated list of tags
+ * from the ADB_TRACE environment variable and build the trace
+ * mask from it. note that '1' and 'all' are special cases to
+ * enable all tracing
+ */
+void  adb_trace_init(void)
+{
+    const char*  p = getenv("ADB_TRACE");
+    const char*  q;
+
+    static const struct {
+        const char*  tag;
+        int           flag;
+    } tags[] = {
+        { "1", 0 },
+        { "all", 0 },
+        { "adb", TRACE_ADB },
+        { "sockets", TRACE_SOCKETS },
+        { "packets", TRACE_PACKETS },
+        { "rwx", TRACE_RWX },
+        { "usb", TRACE_USB },
+        { "sync", TRACE_SYNC },
+        { "sysdeps", TRACE_SYSDEPS },
+        { "transport", TRACE_TRANSPORT },
+        { "jdwp", TRACE_JDWP },
+        { "services", TRACE_SERVICES },
+        { "auth", TRACE_AUTH },
+        { NULL, 0 }
+    };
+
+    if (p == NULL)
+            return;
+
+    /* use a comma/column/semi-colum/space separated list */
+    while (*p) {
+        int  len, tagn;
+
+        q = strpbrk(p, " ,:;");
+        if (q == NULL) {
+            q = p + strlen(p);
+        }
+        len = q - p;
+
+        for (tagn = 0; tags[tagn].tag != NULL; tagn++)
+        {
+            int  taglen = strlen(tags[tagn].tag);
+
+            if (len == taglen && !memcmp(tags[tagn].tag, p, len) )
+            {
+                int  flag = tags[tagn].flag;
+                if (flag == 0) {
+                    adb_trace_mask = ~0;
+                    return;
+                }
+                adb_trace_mask |= (1 << flag);
+                break;
+            }
+        }
+        p = q;
+        if (*p)
+            p++;
+    }
+}
+
+#if !ADB_HOST
+/*
+ * Implements ADB tracing inside the emulator.
+ */
+
+#include <stdarg.h>
+
+/*
+ * Redefine open and write for qemu_pipe.h that contains inlined references
+ * to those routines. We will redifine them back after qemu_pipe.h inclusion.
+ */
+
+#undef open
+#undef write
+#define open    adb_open
+#define write   adb_write
+#include <hardware/qemu_pipe.h>
+#undef open
+#undef write
+#define open    ___xxx_open
+#define write   ___xxx_write
+
+/* A handle to adb-debug qemud service in the emulator. */
+int   adb_debug_qemu = -1;
+
+/* Initializes connection with the adb-debug qemud service in the emulator. */
+static int adb_qemu_trace_init(void)
+{
+    char con_name[32];
+
+    if (adb_debug_qemu >= 0) {
+        return 0;
+    }
+
+    /* adb debugging QEMUD service connection request. */
+    snprintf(con_name, sizeof(con_name), "qemud:adb-debug");
+    adb_debug_qemu = qemu_pipe_open(con_name);
+    return (adb_debug_qemu >= 0) ? 0 : -1;
+}
+
+void adb_qemu_trace(const char* fmt, ...)
+{
+    va_list args;
+    va_start(args, fmt);
+    char msg[1024];
+
+    if (adb_debug_qemu >= 0) {
+        vsnprintf(msg, sizeof(msg), fmt, args);
+        adb_write(adb_debug_qemu, msg, strlen(msg));
+    }
+}
+#endif  /* !ADB_HOST */
+
+apacket *get_apacket(void)
+{
+    apacket *p = malloc(sizeof(apacket));
+    if(p == 0) fatal("failed to allocate an apacket");
+    memset(p, 0, sizeof(apacket) - MAX_PAYLOAD);
+    return p;
+}
+
+void put_apacket(apacket *p)
+{
+    free(p);
+}
+
+void handle_online(atransport *t)
+{
+    D("adb: online\n");
+    t->online = 1;
+}
+
+void handle_offline(atransport *t)
+{
+    D("adb: offline\n");
+    //Close the associated usb
+    t->online = 0;
+    run_transport_disconnects(t);
+}
+
+#if DEBUG_PACKETS
+#define DUMPMAX 32
+void print_packet(const char *label, apacket *p)
+{
+    char *tag;
+    char *x;
+    unsigned count;
+
+    switch(p->msg.command){
+    case A_SYNC: tag = "SYNC"; break;
+    case A_CNXN: tag = "CNXN" ; break;
+    case A_OPEN: tag = "OPEN"; break;
+    case A_OKAY: tag = "OKAY"; break;
+    case A_CLSE: tag = "CLSE"; break;
+    case A_WRTE: tag = "WRTE"; break;
+    case A_AUTH: tag = "AUTH"; break;
+    default: tag = "????"; break;
+    }
+
+    fprintf(stderr, "%s: %s %08x %08x %04x \"",
+            label, tag, p->msg.arg0, p->msg.arg1, p->msg.data_length);
+    count = p->msg.data_length;
+    x = (char*) p->data;
+    if(count > DUMPMAX) {
+        count = DUMPMAX;
+        tag = "\n";
+    } else {
+        tag = "\"\n";
+    }
+    while(count-- > 0){
+        if((*x >= ' ') && (*x < 127)) {
+            fputc(*x, stderr);
+        } else {
+            fputc('.', stderr);
+        }
+        x++;
+    }
+    fputs(tag, stderr);
+}
+#endif
+
+static void send_ready(unsigned local, unsigned remote, atransport *t)
+{
+    D("Calling send_ready \n");
+    apacket *p = get_apacket();
+    p->msg.command = A_OKAY;
+    p->msg.arg0 = local;
+    p->msg.arg1 = remote;
+    send_packet(p, t);
+}
+
+static void send_close(unsigned local, unsigned remote, atransport *t)
+{
+    D("Calling send_close \n");
+    apacket *p = get_apacket();
+    p->msg.command = A_CLSE;
+    p->msg.arg0 = local;
+    p->msg.arg1 = remote;
+    send_packet(p, t);
+}
+
+static size_t fill_connect_data(char *buf, size_t bufsize)
+{
+#if ADB_HOST
+    return snprintf(buf, bufsize, "host::") + 1;
+#else
+    static const char *cnxn_props[] = {
+        "ro.product.name",
+        "ro.product.model",
+        "ro.product.device",
+    };
+    static const int num_cnxn_props = ARRAY_SIZE(cnxn_props);
+    int i;
+    size_t remaining = bufsize;
+    size_t len;
+
+    len = snprintf(buf, remaining, "%s::", adb_device_banner);
+    remaining -= len;
+    buf += len;
+    for (i = 0; i < num_cnxn_props; i++) {
+        char value[PROPERTY_VALUE_MAX];
+        property_get(cnxn_props[i], value, "");
+        len = snprintf(buf, remaining, "%s=%s;", cnxn_props[i], value);
+        remaining -= len;
+        buf += len;
+    }
+
+    return bufsize - remaining + 1;
+#endif
+}
+
+#if !ADB_HOST
+static void send_msg_with_header(int fd, const char* msg, size_t msglen) {
+    char header[5];
+    if (msglen > 0xffff)
+        msglen = 0xffff;
+    snprintf(header, sizeof(header), "%04x", (unsigned)msglen);
+    writex(fd, header, 4);
+    writex(fd, msg, msglen);
+}
+#endif
+
+static void send_msg_with_okay(int fd, const char* msg, size_t msglen) {
+    char header[9];
+    if (msglen > 0xffff)
+        msglen = 0xffff;
+    snprintf(header, sizeof(header), "OKAY%04x", (unsigned)msglen);
+    writex(fd, header, 8);
+    writex(fd, msg, msglen);
+}
+
+static void send_connect(atransport *t)
+{
+    D("Calling send_connect \n");
+    apacket *cp = get_apacket();
+    cp->msg.command = A_CNXN;
+    cp->msg.arg0 = A_VERSION;
+    cp->msg.arg1 = MAX_PAYLOAD;
+    cp->msg.data_length = fill_connect_data((char *)cp->data,
+                                            sizeof(cp->data));
+    send_packet(cp, t);
+}
+
+void send_auth_request(atransport *t)
+{
+    D("Calling send_auth_request\n");
+    apacket *p;
+    int ret;
+
+    ret = adb_auth_generate_token(t->token, sizeof(t->token));
+    if (ret != sizeof(t->token)) {
+        D("Error generating token ret=%d\n", ret);
+        return;
+    }
+
+    p = get_apacket();
+    memcpy(p->data, t->token, ret);
+    p->msg.command = A_AUTH;
+    p->msg.arg0 = ADB_AUTH_TOKEN;
+    p->msg.data_length = ret;
+    send_packet(p, t);
+}
+
+static void send_auth_response(uint8_t *token, size_t token_size, atransport *t)
+{
+    D("Calling send_auth_response\n");
+    apacket *p = get_apacket();
+    int ret;
+
+    ret = adb_auth_sign(t->key, token, token_size, p->data);
+    if (!ret) {
+        D("Error signing the token\n");
+        put_apacket(p);
+        return;
+    }
+
+    p->msg.command = A_AUTH;
+    p->msg.arg0 = ADB_AUTH_SIGNATURE;
+    p->msg.data_length = ret;
+    send_packet(p, t);
+}
+
+static void send_auth_publickey(atransport *t)
+{
+    D("Calling send_auth_publickey\n");
+    apacket *p = get_apacket();
+    int ret;
+
+    ret = adb_auth_get_userkey(p->data, sizeof(p->data));
+    if (!ret) {
+        D("Failed to get user public key\n");
+        put_apacket(p);
+        return;
+    }
+
+    p->msg.command = A_AUTH;
+    p->msg.arg0 = ADB_AUTH_RSAPUBLICKEY;
+    p->msg.data_length = ret;
+    send_packet(p, t);
+}
+
+void adb_auth_verified(atransport *t)
+{
+    handle_online(t);
+    send_connect(t);
+}
+
+static char *connection_state_name(atransport *t)
+{
+    if (t == NULL) {
+        return "unknown";
+    }
+
+    switch(t->connection_state) {
+    case CS_BOOTLOADER:
+        return "bootloader";
+    case CS_DEVICE:
+        return "device";
+    case CS_RECOVERY:
+        return "recovery";
+    case CS_SIDELOAD:
+        return "sideload";
+    case CS_OFFLINE:
+        return "offline";
+    case CS_UNAUTHORIZED:
+        return "unauthorized";
+    default:
+        return "unknown";
+    }
+}
+
+/* qual_overwrite is used to overwrite a qualifier string.  dst is a
+ * pointer to a char pointer.  It is assumed that if *dst is non-NULL, it
+ * was malloc'ed and needs to freed.  *dst will be set to a dup of src.
+ */
+static void qual_overwrite(char **dst, const char *src)
+{
+    if (!dst)
+        return;
+
+    free(*dst);
+    *dst = NULL;
+
+    if (!src || !*src)
+        return;
+
+    *dst = strdup(src);
+}
+
+void parse_banner(char *banner, atransport *t)
+{
+    static const char *prop_seps = ";";
+    static const char key_val_sep = '=';
+    char *cp;
+    char *type;
+
+    D("parse_banner: %s\n", banner);
+    type = banner;
+    cp = strchr(type, ':');
+    if (cp) {
+        *cp++ = 0;
+        /* Nothing is done with second field. */
+        cp = strchr(cp, ':');
+        if (cp) {
+            char *save;
+            char *key;
+            key = adb_strtok_r(cp + 1, prop_seps, &save);
+            while (key) {
+                cp = strchr(key, key_val_sep);
+                if (cp) {
+                    *cp++ = '\0';
+                    if (!strcmp(key, "ro.product.name"))
+                        qual_overwrite(&t->product, cp);
+                    else if (!strcmp(key, "ro.product.model"))
+                        qual_overwrite(&t->model, cp);
+                    else if (!strcmp(key, "ro.product.device"))
+                        qual_overwrite(&t->device, cp);
+                }
+                key = adb_strtok_r(NULL, prop_seps, &save);
+            }
+        }
+    }
+
+    if(!strcmp(type, "bootloader")){
+        D("setting connection_state to CS_BOOTLOADER\n");
+        t->connection_state = CS_BOOTLOADER;
+        update_transports();
+        return;
+    }
+
+    if(!strcmp(type, "device")) {
+        D("setting connection_state to CS_DEVICE\n");
+        t->connection_state = CS_DEVICE;
+        update_transports();
+        return;
+    }
+
+    if(!strcmp(type, "recovery")) {
+        D("setting connection_state to CS_RECOVERY\n");
+        t->connection_state = CS_RECOVERY;
+        update_transports();
+        return;
+    }
+
+    if(!strcmp(type, "sideload")) {
+        D("setting connection_state to CS_SIDELOAD\n");
+        t->connection_state = CS_SIDELOAD;
+        update_transports();
+        return;
+    }
+
+    t->connection_state = CS_HOST;
+}
+
+void handle_packet(apacket *p, atransport *t)
+{
+    asocket *s;
+
+    D("handle_packet() %c%c%c%c\n", ((char*) (&(p->msg.command)))[0],
+            ((char*) (&(p->msg.command)))[1],
+            ((char*) (&(p->msg.command)))[2],
+            ((char*) (&(p->msg.command)))[3]);
+    print_packet("recv", p);
+
+    switch(p->msg.command){
+    case A_SYNC:
+        if(p->msg.arg0){
+            send_packet(p, t);
+            if(HOST) send_connect(t);
+        } else {
+            t->connection_state = CS_OFFLINE;
+            handle_offline(t);
+            send_packet(p, t);
+        }
+        return;
+
+    case A_CNXN: /* CONNECT(version, maxdata, "system-id-string") */
+            /* XXX verify version, etc */
+        if(t->connection_state != CS_OFFLINE) {
+            t->connection_state = CS_OFFLINE;
+            handle_offline(t);
+        }
+
+        parse_banner((char*) p->data, t);
+
+        if (HOST || !auth_enabled) {
+            handle_online(t);
+            if(!HOST) send_connect(t);
+        } else {
+            send_auth_request(t);
+        }
+        break;
+
+    case A_AUTH:
+        if (p->msg.arg0 == ADB_AUTH_TOKEN) {
+            t->connection_state = CS_UNAUTHORIZED;
+            t->key = adb_auth_nextkey(t->key);
+            if (t->key) {
+                send_auth_response(p->data, p->msg.data_length, t);
+            } else {
+                /* No more private keys to try, send the public key */
+                send_auth_publickey(t);
+            }
+        } else if (p->msg.arg0 == ADB_AUTH_SIGNATURE) {
+            if (adb_auth_verify(t->token, p->data, p->msg.data_length)) {
+                adb_auth_verified(t);
+                t->failed_auth_attempts = 0;
+            } else {
+                if (t->failed_auth_attempts++ > 10)
+                    adb_sleep_ms(1000);
+                send_auth_request(t);
+            }
+        } else if (p->msg.arg0 == ADB_AUTH_RSAPUBLICKEY) {
+            adb_auth_confirm_key(p->data, p->msg.data_length, t);
+        }
+        break;
+
+    case A_OPEN: /* OPEN(local-id, 0, "destination") */
+        if (t->online && p->msg.arg0 != 0 && p->msg.arg1 == 0) {
+            char *name = (char*) p->data;
+            name[p->msg.data_length > 0 ? p->msg.data_length - 1 : 0] = 0;
+            s = create_local_service_socket(name);
+            if(s == 0) {
+                send_close(0, p->msg.arg0, t);
+            } else {
+                s->peer = create_remote_socket(p->msg.arg0, t);
+                s->peer->peer = s;
+                send_ready(s->id, s->peer->id, t);
+                s->ready(s);
+            }
+        }
+        break;
+
+    case A_OKAY: /* READY(local-id, remote-id, "") */
+        if (t->online && p->msg.arg0 != 0 && p->msg.arg1 != 0) {
+            if((s = find_local_socket(p->msg.arg1, 0))) {
+                if(s->peer == 0) {
+                    /* On first READY message, create the connection. */
+                    s->peer = create_remote_socket(p->msg.arg0, t);
+                    s->peer->peer = s;
+                    s->ready(s);
+                } else if (s->peer->id == p->msg.arg0) {
+                    /* Other READY messages must use the same local-id */
+                    s->ready(s);
+                } else {
+                    D("Invalid A_OKAY(%d,%d), expected A_OKAY(%d,%d) on transport %s\n",
+                      p->msg.arg0, p->msg.arg1, s->peer->id, p->msg.arg1, t->serial);
+                }
+            }
+        }
+        break;
+
+    case A_CLSE: /* CLOSE(local-id, remote-id, "") or CLOSE(0, remote-id, "") */
+        if (t->online && p->msg.arg1 != 0) {
+            if((s = find_local_socket(p->msg.arg1, p->msg.arg0))) {
+                /* According to protocol.txt, p->msg.arg0 might be 0 to indicate
+                 * a failed OPEN only. However, due to a bug in previous ADB
+                 * versions, CLOSE(0, remote-id, "") was also used for normal
+                 * CLOSE() operations.
+                 *
+                 * This is bad because it means a compromised adbd could
+                 * send packets to close connections between the host and
+                 * other devices. To avoid this, only allow this if the local
+                 * socket has a peer on the same transport.
+                 */
+                if (p->msg.arg0 == 0 && s->peer && s->peer->transport != t) {
+                    D("Invalid A_CLSE(0, %u) from transport %s, expected transport %s\n",
+                      p->msg.arg1, t->serial, s->peer->transport->serial);
+                } else {
+                    s->close(s);
+                }
+            }
+        }
+        break;
+
+    case A_WRTE: /* WRITE(local-id, remote-id, <data>) */
+        if (t->online && p->msg.arg0 != 0 && p->msg.arg1 != 0) {
+            if((s = find_local_socket(p->msg.arg1, p->msg.arg0))) {
+                unsigned rid = p->msg.arg0;
+                p->len = p->msg.data_length;
+
+                if(s->enqueue(s, p) == 0) {
+                    D("Enqueue the socket\n");
+                    send_ready(s->id, rid, t);
+                }
+                return;
+            }
+        }
+        break;
+
+    default:
+        printf("handle_packet: what is %08x?!\n", p->msg.command);
+    }
+
+    put_apacket(p);
+}
+
+alistener listener_list = {
+    .next = &listener_list,
+    .prev = &listener_list,
+};
+
+static void ss_listener_event_func(int _fd, unsigned ev, void *_l)
+{
+    asocket *s;
+
+    if(ev & FDE_READ) {
+        struct sockaddr addr;
+        socklen_t alen;
+        int fd;
+
+        alen = sizeof(addr);
+        fd = adb_socket_accept(_fd, &addr, &alen);
+        if(fd < 0) return;
+
+        adb_socket_setbufsize(fd, CHUNK_SIZE);
+
+        s = create_local_socket(fd);
+        if(s) {
+            connect_to_smartsocket(s);
+            return;
+        }
+
+        adb_close(fd);
+    }
+}
+
+static void listener_event_func(int _fd, unsigned ev, void *_l)
+{
+    alistener *l = _l;
+    asocket *s;
+
+    if(ev & FDE_READ) {
+        struct sockaddr addr;
+        socklen_t alen;
+        int fd;
+
+        alen = sizeof(addr);
+        fd = adb_socket_accept(_fd, &addr, &alen);
+        if(fd < 0) return;
+
+        s = create_local_socket(fd);
+        if(s) {
+            s->transport = l->transport;
+            connect_to_remote(s, l->connect_to);
+            return;
+        }
+
+        adb_close(fd);
+    }
+}
+
+static void  free_listener(alistener*  l)
+{
+    if (l->next) {
+        l->next->prev = l->prev;
+        l->prev->next = l->next;
+        l->next = l->prev = l;
+    }
+
+    // closes the corresponding fd
+    fdevent_remove(&l->fde);
+
+    if (l->local_name)
+        free((char*)l->local_name);
+
+    if (l->connect_to)
+        free((char*)l->connect_to);
+
+    if (l->transport) {
+        remove_transport_disconnect(l->transport, &l->disconnect);
+    }
+    free(l);
+}
+
+static void listener_disconnect(void*  _l, atransport*  t)
+{
+    alistener*  l = _l;
+
+    free_listener(l);
+}
+
+int local_name_to_fd(const char *name)
+{
+    int port;
+
+    if(!strncmp("tcp:", name, 4)){
+        int  ret;
+        port = atoi(name + 4);
+
+        if (gListenAll > 0) {
+            ret = socket_inaddr_any_server(port, SOCK_STREAM);
+        } else {
+            ret = socket_loopback_server(port, SOCK_STREAM);
+        }
+
+        return ret;
+    }
+#ifndef HAVE_WIN32_IPC  /* no Unix-domain sockets on Win32 */
+    // It's non-sensical to support the "reserved" space on the adb host side
+    if(!strncmp(name, "local:", 6)) {
+        return socket_local_server(name + 6,
+                ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
+    } else if(!strncmp(name, "localabstract:", 14)) {
+        return socket_local_server(name + 14,
+                ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
+    } else if(!strncmp(name, "localfilesystem:", 16)) {
+        return socket_local_server(name + 16,
+                ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM);
+    }
+
+#endif
+    printf("unknown local portname '%s'\n", name);
+    return -1;
+}
+
+// Write a single line describing a listener to a user-provided buffer.
+// Appends a trailing zero, even in case of truncation, but the function
+// returns the full line length.
+// If |buffer| is NULL, does not write but returns required size.
+static int format_listener(alistener* l, char* buffer, size_t buffer_len) {
+    // Format is simply:
+    //
+    //  <device-serial> " " <local-name> " " <remote-name> "\n"
+    //
+    int local_len = strlen(l->local_name);
+    int connect_len = strlen(l->connect_to);
+    int serial_len = strlen(l->transport->serial);
+
+    if (buffer != NULL) {
+        snprintf(buffer, buffer_len, "%s %s %s\n",
+                l->transport->serial, l->local_name, l->connect_to);
+    }
+    // NOTE: snprintf() on Windows returns -1 in case of truncation, so
+    // return the computed line length instead.
+    return local_len + connect_len + serial_len + 3;
+}
+
+// Write the list of current listeners (network redirections) into a
+// user-provided buffer. Appends a trailing zero, even in case of
+// trunctaion, but return the full size in bytes.
+// If |buffer| is NULL, does not write but returns required size.
+static int format_listeners(char* buf, size_t buflen)
+{
+    alistener* l;
+    int result = 0;
+    for (l = listener_list.next; l != &listener_list; l = l->next) {
+        // Ignore special listeners like those for *smartsocket*
+        if (l->connect_to[0] == '*')
+          continue;
+        int len = format_listener(l, buf, buflen);
+        // Ensure there is space for the trailing zero.
+        result += len;
+        if (buf != NULL) {
+          buf += len;
+          buflen -= len;
+          if (buflen <= 0)
+              break;
+        }
+    }
+    return result;
+}
+
+static int remove_listener(const char *local_name, atransport* transport)
+{
+    alistener *l;
+
+    for (l = listener_list.next; l != &listener_list; l = l->next) {
+        if (!strcmp(local_name, l->local_name)) {
+            listener_disconnect(l, l->transport);
+            return 0;
+        }
+    }
+    return -1;
+}
+
+static void remove_all_listeners(void)
+{
+    alistener *l, *l_next;
+    for (l = listener_list.next; l != &listener_list; l = l_next) {
+        l_next = l->next;
+        // Never remove smart sockets.
+        if (l->connect_to[0] == '*')
+            continue;
+        listener_disconnect(l, l->transport);
+    }
+}
+
+// error/status codes for install_listener.
+typedef enum {
+  INSTALL_STATUS_OK = 0,
+  INSTALL_STATUS_INTERNAL_ERROR = -1,
+  INSTALL_STATUS_CANNOT_BIND = -2,
+  INSTALL_STATUS_CANNOT_REBIND = -3,
+} install_status_t;
+
+static install_status_t install_listener(const char *local_name,
+                                         const char *connect_to,
+                                         atransport* transport,
+                                         int no_rebind)
+{
+    alistener *l;
+
+    //printf("install_listener('%s','%s')\n", local_name, connect_to);
+
+    for(l = listener_list.next; l != &listener_list; l = l->next){
+        if(strcmp(local_name, l->local_name) == 0) {
+            char *cto;
+
+                /* can't repurpose a smartsocket */
+            if(l->connect_to[0] == '*') {
+                return INSTALL_STATUS_INTERNAL_ERROR;
+            }
+
+                /* can't repurpose a listener if 'no_rebind' is true */
+            if (no_rebind) {
+                return INSTALL_STATUS_CANNOT_REBIND;
+            }
+
+            cto = strdup(connect_to);
+            if(cto == 0) {
+                return INSTALL_STATUS_INTERNAL_ERROR;
+            }
+
+            //printf("rebinding '%s' to '%s'\n", local_name, connect_to);
+            free((void*) l->connect_to);
+            l->connect_to = cto;
+            if (l->transport != transport) {
+                remove_transport_disconnect(l->transport, &l->disconnect);
+                l->transport = transport;
+                add_transport_disconnect(l->transport, &l->disconnect);
+            }
+            return INSTALL_STATUS_OK;
+        }
+    }
+
+    if((l = calloc(1, sizeof(alistener))) == 0) goto nomem;
+    if((l->local_name = strdup(local_name)) == 0) goto nomem;
+    if((l->connect_to = strdup(connect_to)) == 0) goto nomem;
+
+
+    l->fd = local_name_to_fd(local_name);
+    if(l->fd < 0) {
+        free((void*) l->local_name);
+        free((void*) l->connect_to);
+        free(l);
+        printf("cannot bind '%s'\n", local_name);
+        return -2;
+    }
+
+    close_on_exec(l->fd);
+    if(!strcmp(l->connect_to, "*smartsocket*")) {
+        fdevent_install(&l->fde, l->fd, ss_listener_event_func, l);
+    } else {
+        fdevent_install(&l->fde, l->fd, listener_event_func, l);
+    }
+    fdevent_set(&l->fde, FDE_READ);
+
+    l->next = &listener_list;
+    l->prev = listener_list.prev;
+    l->next->prev = l;
+    l->prev->next = l;
+    l->transport = transport;
+
+    if (transport) {
+        l->disconnect.opaque = l;
+        l->disconnect.func   = listener_disconnect;
+        add_transport_disconnect(transport, &l->disconnect);
+    }
+    return INSTALL_STATUS_OK;
+
+nomem:
+    fatal("cannot allocate listener");
+    return INSTALL_STATUS_INTERNAL_ERROR;
+}
+
+#ifdef HAVE_WIN32_PROC
+static BOOL WINAPI ctrlc_handler(DWORD type)
+{
+    exit(STATUS_CONTROL_C_EXIT);
+    return TRUE;
+}
+#endif
+
+static void adb_cleanup(void)
+{
+    usb_cleanup();
+}
+
+void start_logging(void)
+{
+#ifdef HAVE_WIN32_PROC
+    char    temp[ MAX_PATH ];
+    FILE*   fnul;
+    FILE*   flog;
+
+    GetTempPath( sizeof(temp) - 8, temp );
+    strcat( temp, "adb.log" );
+
+    /* Win32 specific redirections */
+    fnul = fopen( "NUL", "rt" );
+    if (fnul != NULL)
+        stdin[0] = fnul[0];
+
+    flog = fopen( temp, "at" );
+    if (flog == NULL)
+        flog = fnul;
+
+    setvbuf( flog, NULL, _IONBF, 0 );
+
+    stdout[0] = flog[0];
+    stderr[0] = flog[0];
+    fprintf(stderr,"--- adb starting (pid %d) ---\n", getpid());
+#else
+    int fd;
+
+    fd = unix_open("/dev/null", O_RDONLY);
+    dup2(fd, 0);
+    adb_close(fd);
+
+    fd = unix_open("/tmp/adb.log", O_WRONLY | O_CREAT | O_APPEND, 0640);
+    if(fd < 0) {
+        fd = unix_open("/dev/null", O_WRONLY);
+    }
+    dup2(fd, 1);
+    dup2(fd, 2);
+    adb_close(fd);
+    fprintf(stderr,"--- adb starting (pid %d) ---\n", getpid());
+#endif
+}
+
+#if !ADB_HOST
+void start_device_log(void)
+{
+    int fd;
+    char    path[PATH_MAX];
+    struct tm now;
+    time_t t;
+    char value[PROPERTY_VALUE_MAX];
+
+    // read the trace mask from persistent property persist.adb.trace_mask
+    // give up if the property is not set or cannot be parsed
+    property_get("persist.adb.trace_mask", value, "");
+    if (sscanf(value, "%x", &adb_trace_mask) != 1)
+        return;
+
+    adb_mkdir("/data/adb", 0775);
+    tzset();
+    time(&t);
+    localtime_r(&t, &now);
+    strftime(path, sizeof(path),
+                "/data/adb/adb-%Y-%m-%d-%H-%M-%S.txt",
+                &now);
+    fd = unix_open(path, O_WRONLY | O_CREAT | O_TRUNC, 0640);
+    if (fd < 0)
+        return;
+
+    // redirect stdout and stderr to the log file
+    dup2(fd, 1);
+    dup2(fd, 2);
+    fprintf(stderr,"--- adb starting (pid %d) ---\n", getpid());
+    adb_close(fd);
+
+    fd = unix_open("/dev/null", O_RDONLY);
+    dup2(fd, 0);
+    adb_close(fd);
+}
+#endif
+
+#if ADB_HOST
+
+#ifdef WORKAROUND_BUG6558362
+#include <sched.h>
+#define AFFINITY_ENVVAR "ADB_CPU_AFFINITY_BUG6558362"
+void adb_set_affinity(void)
+{
+   cpu_set_t cpu_set;
+   const char* cpunum_str = getenv(AFFINITY_ENVVAR);
+   char* strtol_res;
+   int cpu_num;
+
+   if (!cpunum_str || !*cpunum_str)
+       return;
+   cpu_num = strtol(cpunum_str, &strtol_res, 0);
+   if (*strtol_res != '\0')
+     fatal("bad number (%s) in env var %s. Expecting 0..n.\n", cpunum_str, AFFINITY_ENVVAR);
+
+   sched_getaffinity(0, sizeof(cpu_set), &cpu_set);
+   D("orig cpu_set[0]=0x%08lx\n", cpu_set.__bits[0]);
+   CPU_ZERO(&cpu_set);
+   CPU_SET(cpu_num, &cpu_set);
+   sched_setaffinity(0, sizeof(cpu_set), &cpu_set);
+   sched_getaffinity(0, sizeof(cpu_set), &cpu_set);
+   D("new cpu_set[0]=0x%08lx\n", cpu_set.__bits[0]);
+}
+#endif
+
+int launch_server(int server_port)
+{
+#ifdef HAVE_WIN32_PROC
+    /* we need to start the server in the background                    */
+    /* we create a PIPE that will be used to wait for the server's "OK" */
+    /* message since the pipe handles must be inheritable, we use a     */
+    /* security attribute                                               */
+    HANDLE                pipe_read, pipe_write;
+    HANDLE                stdout_handle, stderr_handle;
+    SECURITY_ATTRIBUTES   sa;
+    STARTUPINFO           startup;
+    PROCESS_INFORMATION   pinfo;
+    char                  program_path[ MAX_PATH ];
+    int                   ret;
+
+    sa.nLength = sizeof(sa);
+    sa.lpSecurityDescriptor = NULL;
+    sa.bInheritHandle = TRUE;
+
+    /* create pipe, and ensure its read handle isn't inheritable */
+    ret = CreatePipe( &pipe_read, &pipe_write, &sa, 0 );
+    if (!ret) {
+        fprintf(stderr, "CreatePipe() failure, error %ld\n", GetLastError() );
+        return -1;
+    }
+
+    SetHandleInformation( pipe_read, HANDLE_FLAG_INHERIT, 0 );
+
+    /* Some programs want to launch an adb command and collect its output by
+     * calling CreateProcess with inheritable stdout/stderr handles, then
+     * using read() to get its output. When this happens, the stdout/stderr
+     * handles passed to the adb client process will also be inheritable.
+     * When starting the adb server here, care must be taken to reset them
+     * to non-inheritable.
+     * Otherwise, something bad happens: even if the adb command completes,
+     * the calling process is stuck while read()-ing from the stdout/stderr
+     * descriptors, because they're connected to corresponding handles in the
+     * adb server process (even if the latter never uses/writes to them).
+     */
+    stdout_handle = GetStdHandle( STD_OUTPUT_HANDLE );
+    stderr_handle = GetStdHandle( STD_ERROR_HANDLE );
+    if (stdout_handle != INVALID_HANDLE_VALUE) {
+        SetHandleInformation( stdout_handle, HANDLE_FLAG_INHERIT, 0 );
+    }
+    if (stderr_handle != INVALID_HANDLE_VALUE) {
+        SetHandleInformation( stderr_handle, HANDLE_FLAG_INHERIT, 0 );
+    }
+
+    ZeroMemory( &startup, sizeof(startup) );
+    startup.cb = sizeof(startup);
+    startup.hStdInput  = GetStdHandle( STD_INPUT_HANDLE );
+    startup.hStdOutput = pipe_write;
+    startup.hStdError  = GetStdHandle( STD_ERROR_HANDLE );
+    startup.dwFlags    = STARTF_USESTDHANDLES;
+
+    ZeroMemory( &pinfo, sizeof(pinfo) );
+
+    /* get path of current program */
+    GetModuleFileName( NULL, program_path, sizeof(program_path) );
+
+    ret = CreateProcess(
+            program_path,                              /* program path  */
+            "adb fork-server server",
+                                    /* the fork-server argument will set the
+                                       debug = 2 in the child           */
+            NULL,                   /* process handle is not inheritable */
+            NULL,                    /* thread handle is not inheritable */
+            TRUE,                          /* yes, inherit some handles */
+            DETACHED_PROCESS, /* the new process doesn't have a console */
+            NULL,                     /* use parent's environment block */
+            NULL,                    /* use parent's starting directory */
+            &startup,                 /* startup info, i.e. std handles */
+            &pinfo );
+
+    CloseHandle( pipe_write );
+
+    if (!ret) {
+        fprintf(stderr, "CreateProcess failure, error %ld\n", GetLastError() );
+        CloseHandle( pipe_read );
+        return -1;
+    }
+
+    CloseHandle( pinfo.hProcess );
+    CloseHandle( pinfo.hThread );
+
+    /* wait for the "OK\n" message */
+    {
+        char  temp[3];
+        DWORD  count;
+
+        ret = ReadFile( pipe_read, temp, 3, &count, NULL );
+        CloseHandle( pipe_read );
+        if ( !ret ) {
+            fprintf(stderr, "could not read ok from ADB Server, error = %ld\n", GetLastError() );
+            return -1;
+        }
+        if (count != 3 || temp[0] != 'O' || temp[1] != 'K' || temp[2] != '\n') {
+            fprintf(stderr, "ADB server didn't ACK\n" );
+            return -1;
+        }
+    }
+#elif defined(HAVE_FORKEXEC)
+    char    path[PATH_MAX];
+    int     fd[2];
+
+    // set up a pipe so the child can tell us when it is ready.
+    // fd[0] will be parent's end, and fd[1] will get mapped to stderr in the child.
+    if (pipe(fd)) {
+        fprintf(stderr, "pipe failed in launch_server, errno: %d\n", errno);
+        return -1;
+    }
+    get_my_path(path, PATH_MAX);
+    pid_t pid = fork();
+    if(pid < 0) return -1;
+
+    if (pid == 0) {
+        // child side of the fork
+
+        // redirect stderr to the pipe
+        // we use stderr instead of stdout due to stdout's buffering behavior.
+        adb_close(fd[0]);
+        dup2(fd[1], STDERR_FILENO);
+        adb_close(fd[1]);
+
+        char str_port[30];
+        snprintf(str_port, sizeof(str_port), "%d",  server_port);
+        // child process
+        int result = execl(path, "adb", "-P", str_port, "fork-server", "server", NULL);
+        // this should not return
+        fprintf(stderr, "OOPS! execl returned %d, errno: %d\n", result, errno);
+    } else  {
+        // parent side of the fork
+
+        char  temp[3];
+
+        temp[0] = 'A'; temp[1] = 'B'; temp[2] = 'C';
+        // wait for the "OK\n" message
+        adb_close(fd[1]);
+        int ret = adb_read(fd[0], temp, 3);
+        int saved_errno = errno;
+        adb_close(fd[0]);
+        if (ret < 0) {
+            fprintf(stderr, "could not read ok from ADB Server, errno = %d\n", saved_errno);
+            return -1;
+        }
+        if (ret != 3 || temp[0] != 'O' || temp[1] != 'K' || temp[2] != '\n') {
+            fprintf(stderr, "ADB server didn't ACK\n" );
+            return -1;
+        }
+
+        setsid();
+    }
+#else
+#error "cannot implement background server start on this platform"
+#endif
+    return 0;
+}
+#endif
+
+/* Constructs a local name of form tcp:port.
+ * target_str points to the target string, it's content will be overwritten.
+ * target_size is the capacity of the target string.
+ * server_port is the port number to use for the local name.
+ */
+void build_local_name(char* target_str, size_t target_size, int server_port)
+{
+  snprintf(target_str, target_size, "tcp:%d", server_port);
+}
+
+#if !ADB_HOST
+
+static void drop_capabilities_bounding_set_if_needed() {
+#ifdef ALLOW_ADBD_ROOT
+    char value[PROPERTY_VALUE_MAX];
+    property_get("ro.debuggable", value, "");
+    if (strcmp(value, "1") == 0) {
+        return;
+    }
+#endif
+    int i;
+    for (i = 0; prctl(PR_CAPBSET_READ, i, 0, 0, 0) >= 0; i++) {
+        if (i == CAP_SETUID || i == CAP_SETGID) {
+            // CAP_SETUID CAP_SETGID needed by /system/bin/run-as
+            continue;
+        }
+        int err = prctl(PR_CAPBSET_DROP, i, 0, 0, 0);
+
+        // Some kernels don't have file capabilities compiled in, and
+        // prctl(PR_CAPBSET_DROP) returns EINVAL. Don't automatically
+        // die when we see such misconfigured kernels.
+        if ((err < 0) && (errno != EINVAL)) {
+            exit(1);
+        }
+    }
+}
+
+static int should_drop_privileges() {
+#ifndef ALLOW_ADBD_ROOT
+    return 1;
+#else /* ALLOW_ADBD_ROOT */
+    int secure = 0;
+    char value[PROPERTY_VALUE_MAX];
+
+   /* run adbd in secure mode if ro.secure is set and
+    ** we are not in the emulator
+    */
+    property_get("ro.kernel.qemu", value, "");
+    if (strcmp(value, "1") != 0) {
+        property_get("ro.secure", value, "1");
+        if (strcmp(value, "1") == 0) {
+            // don't run as root if ro.secure is set...
+            secure = 1;
+
+            // ... except we allow running as root in userdebug builds if the
+            // service.adb.root property has been set by the "adb root" command
+            property_get("ro.debuggable", value, "");
+            if (strcmp(value, "1") == 0) {
+                property_get("service.adb.root", value, "");
+                if (strcmp(value, "1") == 0) {
+                    secure = 0;
+                }
+            }
+        }
+    }
+    return secure;
+#endif /* ALLOW_ADBD_ROOT */
+}
+#endif /* !ADB_HOST */
+
+int adb_main(int is_daemon, int server_port)
+{
+#if !ADB_HOST
+    int port;
+    char value[PROPERTY_VALUE_MAX];
+
+    umask(000);
+#endif
+
+    atexit(adb_cleanup);
+#ifdef HAVE_WIN32_PROC
+    SetConsoleCtrlHandler( ctrlc_handler, TRUE );
+#elif defined(HAVE_FORKEXEC)
+    // No SIGCHLD. Let the service subproc handle its children.
+    signal(SIGPIPE, SIG_IGN);
+#endif
+
+    init_transport_registration();
+
+#if ADB_HOST
+    HOST = 1;
+
+#ifdef WORKAROUND_BUG6558362
+    if(is_daemon) adb_set_affinity();
+#endif
+    usb_vendors_init();
+    usb_init();
+    local_init(DEFAULT_ADB_LOCAL_TRANSPORT_PORT);
+    adb_auth_init();
+
+    char local_name[30];
+    build_local_name(local_name, sizeof(local_name), server_port);
+    if(install_listener(local_name, "*smartsocket*", NULL, 0)) {
+        exit(1);
+    }
+#else
+    property_get("ro.adb.secure", value, "0");
+    auth_enabled = !strcmp(value, "1");
+    if (auth_enabled)
+        adb_auth_init();
+
+    // Our external storage path may be different than apps, since
+    // we aren't able to bind mount after dropping root.
+    const char* adb_external_storage = getenv("ADB_EXTERNAL_STORAGE");
+    if (NULL != adb_external_storage) {
+        setenv("EXTERNAL_STORAGE", adb_external_storage, 1);
+    } else {
+        D("Warning: ADB_EXTERNAL_STORAGE is not set.  Leaving EXTERNAL_STORAGE"
+          " unchanged.\n");
+    }
+
+    /* add extra groups:
+    ** AID_ADB to access the USB driver
+    ** AID_LOG to read system logs (adb logcat)
+    ** AID_INPUT to diagnose input issues (getevent)
+    ** AID_INET to diagnose network issues (netcfg, ping)
+    ** AID_GRAPHICS to access the frame buffer
+    ** AID_NET_BT and AID_NET_BT_ADMIN to diagnose bluetooth (hcidump)
+    ** AID_SDCARD_R to allow reading from the SD card
+    ** AID_SDCARD_RW to allow writing to the SD card
+    ** AID_NET_BW_STATS to read out qtaguid statistics
+    */
+    gid_t groups[] = { AID_ADB, AID_LOG, AID_INPUT, AID_INET, AID_GRAPHICS,
+                       AID_NET_BT, AID_NET_BT_ADMIN, AID_SDCARD_R, AID_SDCARD_RW,
+                       AID_NET_BW_STATS };
+    if (setgroups(sizeof(groups)/sizeof(groups[0]), groups) != 0) {
+        exit(1);
+    }
+
+    /* don't listen on a port (default 5037) if running in secure mode */
+    /* don't run as root if we are running in secure mode */
+    if (should_drop_privileges()) {
+        drop_capabilities_bounding_set_if_needed();
+
+        /* then switch user and group to "shell" */
+        if (setgid(AID_SHELL) != 0) {
+            exit(1);
+        }
+        if (setuid(AID_SHELL) != 0) {
+            exit(1);
+        }
+
+        D("Local port disabled\n");
+    } else {
+        char local_name[30];
+        // changed by feilv
+        //if ((root_seclabel != NULL) && (is_selinux_enabled() > 0)) {
+        //    // b/12587913: fix setcon to allow const pointers
+        //    if (setcon((char *)root_seclabel) < 0) {
+        //        exit(1);
+        //    }
+        //}
+        build_local_name(local_name, sizeof(local_name), server_port);
+        if(install_listener(local_name, "*smartsocket*", NULL, 0)) {
+            exit(1);
+        }
+    }
+
+    int usb = 0;
+    if (access(USB_ADB_PATH, F_OK) == 0 || access(USB_FFS_ADB_EP0, F_OK) == 0) {
+        // listen on USB
+        usb_init();
+        usb = 1;
+    }
+
+    // If one of these properties is set, also listen on that port
+    // If one of the properties isn't set and we couldn't listen on usb,
+    // listen on the default port.
+    property_get("service.adb.tcp.port", value, "");
+    if (!value[0]) {
+        property_get("persist.adb.tcp.port", value, "");
+    }
+    if (sscanf(value, "%d", &port) == 1 && port > 0) {
+        printf("using port=%d\n", port);
+        // listen on TCP port specified by service.adb.tcp.port property
+        local_init(port);
+    } else if (!usb) {
+        // listen on default port
+        local_init(DEFAULT_ADB_LOCAL_TRANSPORT_PORT);
+    }
+
+    D("adb_main(): pre init_jdwp()\n");
+    init_jdwp();
+    D("adb_main(): post init_jdwp()\n");
+#endif
+
+    if (is_daemon)
+    {
+        // inform our parent that we are up and running.
+#ifdef HAVE_WIN32_PROC
+        DWORD  count;
+        WriteFile( GetStdHandle( STD_OUTPUT_HANDLE ), "OK\n", 3, &count, NULL );
+#elif defined(HAVE_FORKEXEC)
+        fprintf(stderr, "OK\n");
+#endif
+        start_logging();
+    }
+    D("Event loop starting\n");
+
+    fdevent_loop();
+
+    usb_cleanup();
+
+    return 0;
+}
+
+// Try to handle a network forwarding request.
+// This returns 1 on success, 0 on failure, and -1 to indicate this is not
+// a forwarding-related request.
+int handle_forward_request(const char* service, transport_type ttype, char* serial, int reply_fd)
+{
+    if (!strcmp(service, "list-forward")) {
+        // Create the list of forward redirections.
+        int buffer_size = format_listeners(NULL, 0);
+        // Add one byte for the trailing zero.
+        char* buffer = malloc(buffer_size + 1);
+        if (buffer == NULL) {
+            sendfailmsg(reply_fd, "not enough memory");
+            return 1;
+        }
+        (void) format_listeners(buffer, buffer_size + 1);
+#if ADB_HOST
+        send_msg_with_okay(reply_fd, buffer, buffer_size);
+#else
+        send_msg_with_header(reply_fd, buffer, buffer_size);
+#endif
+        free(buffer);
+        return 1;
+    }
+
+    if (!strcmp(service, "killforward-all")) {
+        remove_all_listeners();
+#if ADB_HOST
+        /* On the host: 1st OKAY is connect, 2nd OKAY is status */
+        adb_write(reply_fd, "OKAY", 4);
+#endif
+        adb_write(reply_fd, "OKAY", 4);
+        return 1;
+    }
+
+    if (!strncmp(service, "forward:",8) ||
+        !strncmp(service, "killforward:",12)) {
+        char *local, *remote, *err;
+        int r;
+        atransport *transport;
+
+        int createForward = strncmp(service, "kill", 4);
+        int no_rebind = 0;
+
+        local = strchr(service, ':') + 1;
+
+        // Handle forward:norebind:<local>... here
+        if (createForward && !strncmp(local, "norebind:", 9)) {
+            no_rebind = 1;
+            local = strchr(local, ':') + 1;
+        }
+
+        remote = strchr(local,';');
+
+        if (createForward) {
+            // Check forward: parameter format: '<local>;<remote>'
+            if(remote == 0) {
+                sendfailmsg(reply_fd, "malformed forward spec");
+                return 1;
+            }
+
+            *remote++ = 0;
+            if((local[0] == 0) || (remote[0] == 0) || (remote[0] == '*')) {
+                sendfailmsg(reply_fd, "malformed forward spec");
+                return 1;
+            }
+        } else {
+            // Check killforward: parameter format: '<local>'
+            if (local[0] == 0) {
+                sendfailmsg(reply_fd, "malformed forward spec");
+                return 1;
+            }
+        }
+
+        transport = acquire_one_transport(CS_ANY, ttype, serial, &err);
+        if (!transport) {
+            sendfailmsg(reply_fd, err);
+            return 1;
+        }
+
+        if (createForward) {
+            r = install_listener(local, remote, transport, no_rebind);
+        } else {
+            r = remove_listener(local, transport);
+        }
+        if(r == 0) {
+#if ADB_HOST
+            /* On the host: 1st OKAY is connect, 2nd OKAY is status */
+            writex(reply_fd, "OKAY", 4);
+#endif
+            writex(reply_fd, "OKAY", 4);
+            return 1;
+        }
+
+        if (createForward) {
+            const char* message;
+            switch (r) {
+              case INSTALL_STATUS_CANNOT_BIND:
+                message = "cannot bind to socket";
+                break;
+              case INSTALL_STATUS_CANNOT_REBIND:
+                message = "cannot rebind existing socket";
+                break;
+              default:
+                message = "internal error";
+            }
+            sendfailmsg(reply_fd, message);
+        } else {
+            sendfailmsg(reply_fd, "cannot remove listener");
+        }
+        return 1;
+    }
+    return 0;
+}
+
+int handle_host_request(char *service, transport_type ttype, char* serial, int reply_fd, asocket *s)
+{
+    atransport *transport = NULL;
+
+    if(!strcmp(service, "kill")) {
+        fprintf(stderr,"adb server killed by remote request\n");
+        fflush(stdout);
+        adb_write(reply_fd, "OKAY", 4);
+        usb_cleanup();
+        exit(0);
+    }
+
+#if ADB_HOST
+    // "transport:" is used for switching transport with a specified serial number
+    // "transport-usb:" is used for switching transport to the only USB transport
+    // "transport-local:" is used for switching transport to the only local transport
+    // "transport-any:" is used for switching transport to the only transport
+    if (!strncmp(service, "transport", strlen("transport"))) {
+        char* error_string = "unknown failure";
+        transport_type type = kTransportAny;
+
+        if (!strncmp(service, "transport-usb", strlen("transport-usb"))) {
+            type = kTransportUsb;
+        } else if (!strncmp(service, "transport-local", strlen("transport-local"))) {
+            type = kTransportLocal;
+        } else if (!strncmp(service, "transport-any", strlen("transport-any"))) {
+            type = kTransportAny;
+        } else if (!strncmp(service, "transport:", strlen("transport:"))) {
+            service += strlen("transport:");
+            serial = service;
+        }
+
+        transport = acquire_one_transport(CS_ANY, type, serial, &error_string);
+
+        if (transport) {
+            s->transport = transport;
+            adb_write(reply_fd, "OKAY", 4);
+        } else {
+            sendfailmsg(reply_fd, error_string);
+        }
+        return 1;
+    }
+
+    // return a list of all connected devices
+    if (!strncmp(service, "devices", 7)) {
+        char buffer[4096];
+        int use_long = !strcmp(service+7, "-l");
+        if (use_long || service[7] == 0) {
+            memset(buffer, 0, sizeof(buffer));
+            D("Getting device list \n");
+            list_transports(buffer, sizeof(buffer), use_long);
+            D("Wrote device list \n");
+            send_msg_with_okay(reply_fd, buffer, strlen(buffer));
+            return 0;
+        }
+    }
+
+    // remove TCP transport
+    if (!strncmp(service, "disconnect:", 11)) {
+        char buffer[4096];
+        memset(buffer, 0, sizeof(buffer));
+        char* serial = service + 11;
+        if (serial[0] == 0) {
+            // disconnect from all TCP devices
+            unregister_all_tcp_transports();
+        } else {
+            char hostbuf[100];
+            // assume port 5555 if no port is specified
+            if (!strchr(serial, ':')) {
+                snprintf(hostbuf, sizeof(hostbuf) - 1, "%s:5555", serial);
+                serial = hostbuf;
+            }
+            atransport *t = find_transport(serial);
+
+            if (t) {
+                unregister_transport(t);
+            } else {
+                snprintf(buffer, sizeof(buffer), "No such device %s", serial);
+            }
+        }
+
+        send_msg_with_okay(reply_fd, buffer, strlen(buffer));
+        return 0;
+    }
+
+    // returns our value for ADB_SERVER_VERSION
+    if (!strcmp(service, "version")) {
+        char version[12];
+        snprintf(version, sizeof version, "%04x", ADB_SERVER_VERSION);
+        send_msg_with_okay(reply_fd, version, strlen(version));
+        return 0;
+    }
+
+    if(!strncmp(service,"get-serialno",strlen("get-serialno"))) {
+        char *out = "unknown";
+         transport = acquire_one_transport(CS_ANY, ttype, serial, NULL);
+       if (transport && transport->serial) {
+            out = transport->serial;
+        }
+        send_msg_with_okay(reply_fd, out, strlen(out));
+        return 0;
+    }
+    if(!strncmp(service,"get-devpath",strlen("get-devpath"))) {
+        char *out = "unknown";
+         transport = acquire_one_transport(CS_ANY, ttype, serial, NULL);
+       if (transport && transport->devpath) {
+            out = transport->devpath;
+        }
+        send_msg_with_okay(reply_fd, out, strlen(out));
+        return 0;
+    }
+    // indicates a new emulator instance has started
+    if (!strncmp(service,"emulator:",9)) {
+        int  port = atoi(service+9);
+        local_connect(port);
+        /* we don't even need to send a reply */
+        return 0;
+    }
+#endif // ADB_HOST
+
+    int ret = handle_forward_request(service, ttype, serial, reply_fd);
+    if (ret >= 0)
+      return ret - 1;
+
+    if(!strncmp(service,"get-state",strlen("get-state"))) {
+        transport = acquire_one_transport(CS_ANY, ttype, serial, NULL);
+        char *state = connection_state_name(transport);
+        send_msg_with_okay(reply_fd, state, strlen(state));
+        return 0;
+    }
+    return -1;
+}
+
+int main(int argc, char **argv)
+{
+#if ADB_HOST
+    adb_sysdeps_init();
+    adb_trace_init();
+    D("Handling commandline()\n");
+    return adb_commandline(argc - 1, argv + 1);
+#else
+    /* If adbd runs inside the emulator this will enable adb tracing via
+     * adb-debug qemud service in the emulator. */
+    adb_qemu_trace_init();
+    // changed by feilv
+    //while(1) {
+    //    int c;
+    //    int option_index = 0;
+    //    static struct option opts[] = {
+    //        {"root_seclabel", required_argument, 0, 's' },
+    //        {"device_banner", required_argument, 0, 'b' }
+    //    };
+    //    c = getopt_long(argc, argv, "", opts, &option_index);
+    //    if (c == -1)
+    //        break;
+    //    switch (c) {
+    //    case 's':
+    //        root_seclabel = optarg;
+    //        break;
+    //    case 'b':
+    //        adb_device_banner = optarg;
+    //        break;
+    //    default:
+    //        break;
+    //    }
+    //}
+
+    start_device_log();
+    D("Handling main()\n");
+    return adb_main(0, DEFAULT_ADB_PORT);
+#endif
+}
diff --git a/package/utils/adbd/src/adb/adb.h b/package/utils/adbd/src/adb/adb.h
new file mode 100644
index 0000000..4704abb
--- /dev/null
+++ b/package/utils/adbd/src/adb/adb.h
@@ -0,0 +1,495 @@
+/*
+ * 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 __ADB_H
+#define __ADB_H
+
+#include <limits.h>
+
+#include "transport.h"  /* readx(), writex() */
+
+#define MAX_PAYLOAD 4096
+
+#define A_SYNC 0x434e5953
+#define A_CNXN 0x4e584e43
+#define A_OPEN 0x4e45504f
+#define A_OKAY 0x59414b4f
+#define A_CLSE 0x45534c43
+#define A_WRTE 0x45545257
+#define A_AUTH 0x48545541
+
+#define A_VERSION 0x01000000        // ADB protocol version
+
+#define ADB_VERSION_MAJOR 1         // Used for help/version information
+#define ADB_VERSION_MINOR 0         // Used for help/version information
+
+#define ADB_SERVER_VERSION    31    // Increment this when we want to force users to start a new adb server
+
+typedef struct amessage amessage;
+typedef struct apacket apacket;
+typedef struct asocket asocket;
+typedef struct alistener alistener;
+typedef struct aservice aservice;
+typedef struct atransport atransport;
+typedef struct adisconnect  adisconnect;
+typedef struct usb_handle usb_handle;
+
+struct amessage {
+    unsigned command;       /* command identifier constant      */
+    unsigned arg0;          /* first argument                   */
+    unsigned arg1;          /* second argument                  */
+    unsigned data_length;   /* length of payload (0 is allowed) */
+    unsigned data_check;    /* checksum of data payload         */
+    unsigned magic;         /* command ^ 0xffffffff             */
+};
+
+struct apacket
+{
+    apacket *next;
+
+    unsigned len;
+    unsigned char *ptr;
+
+    amessage msg;
+    unsigned char data[MAX_PAYLOAD];
+};
+
+/* An asocket represents one half of a connection between a local and
+** remote entity.  A local asocket is bound to a file descriptor.  A
+** remote asocket is bound to the protocol engine.
+*/
+struct asocket {
+        /* chain pointers for the local/remote list of
+        ** asockets that this asocket lives in
+        */
+    asocket *next;
+    asocket *prev;
+
+        /* the unique identifier for this asocket
+        */
+    unsigned id;
+
+        /* flag: set when the socket's peer has closed
+        ** but packets are still queued for delivery
+        */
+    int    closing;
+
+        /* flag: quit adbd when both ends close the
+        ** local service socket
+        */
+    int    exit_on_close;
+
+        /* the asocket we are connected to
+        */
+
+    asocket *peer;
+
+        /* For local asockets, the fde is used to bind
+        ** us to our fd event system.  For remote asockets
+        ** these fields are not used.
+        */
+    fdevent fde;
+    int fd;
+
+        /* queue of apackets waiting to be written
+        */
+    apacket *pkt_first;
+    apacket *pkt_last;
+
+        /* enqueue is called by our peer when it has data
+        ** for us.  It should return 0 if we can accept more
+        ** data or 1 if not.  If we return 1, we must call
+        ** peer->ready() when we once again are ready to
+        ** receive data.
+        */
+    int (*enqueue)(asocket *s, apacket *pkt);
+
+        /* ready is called by the peer when it is ready for
+        ** us to send data via enqueue again
+        */
+    void (*ready)(asocket *s);
+
+        /* shutdown is called by the peer before it goes away.
+        ** the socket should not do any further calls on its peer.
+        ** Always followed by a call to close. Optional, i.e. can be NULL.
+        */
+    void (*shutdown)(asocket *s);
+
+        /* close is called by the peer when it has gone away.
+        ** we are not allowed to make any further calls on the
+        ** peer once our close method is called.
+        */
+    void (*close)(asocket *s);
+
+        /* A socket is bound to atransport */
+    atransport *transport;
+};
+
+
+/* the adisconnect structure is used to record a callback that
+** will be called whenever a transport is disconnected (e.g. by the user)
+** this should be used to cleanup objects that depend on the
+** transport (e.g. remote sockets, listeners, etc...)
+*/
+struct  adisconnect
+{
+    void        (*func)(void*  opaque, atransport*  t);
+    void*         opaque;
+    adisconnect*  next;
+    adisconnect*  prev;
+};
+
+
+/* a transport object models the connection to a remote device or emulator
+** there is one transport per connected device/emulator. a "local transport"
+** connects through TCP (for the emulator), while a "usb transport" through
+** USB (for real devices)
+**
+** note that kTransportHost doesn't really correspond to a real transport
+** object, it's a special value used to indicate that a client wants to
+** connect to a service implemented within the ADB server itself.
+*/
+typedef enum transport_type {
+        kTransportUsb,
+        kTransportLocal,
+        kTransportAny,
+        kTransportHost,
+} transport_type;
+
+#define TOKEN_SIZE 20
+
+struct atransport
+{
+    atransport *next;
+    atransport *prev;
+
+    int (*read_from_remote)(apacket *p, atransport *t);
+    int (*write_to_remote)(apacket *p, atransport *t);
+    void (*close)(atransport *t);
+    void (*kick)(atransport *t);
+
+    int fd;
+    int transport_socket;
+    fdevent transport_fde;
+    int ref_count;
+    unsigned sync_token;
+    int connection_state;
+    int online;
+    transport_type type;
+
+        /* usb handle or socket fd as needed */
+    usb_handle *usb;
+    int sfd;
+
+        /* used to identify transports for clients */
+    char *serial;
+    char *product;
+    char *model;
+    char *device;
+    char *devpath;
+    int adb_port; // Use for emulators (local transport)
+
+        /* a list of adisconnect callbacks called when the transport is kicked */
+    int          kicked;
+    adisconnect  disconnects;
+
+    void *key;
+    unsigned char token[TOKEN_SIZE];
+    fdevent auth_fde;
+    unsigned failed_auth_attempts;
+};
+
+
+/* A listener is an entity which binds to a local port
+** and, upon receiving a connection on that port, creates
+** an asocket to connect the new local connection to a
+** specific remote service.
+**
+** TODO: some listeners read from the new connection to
+** determine what exact service to connect to on the far
+** side.
+*/
+struct alistener
+{
+    alistener *next;
+    alistener *prev;
+
+    fdevent fde;
+    int fd;
+
+    const char *local_name;
+    const char *connect_to;
+    atransport *transport;
+    adisconnect  disconnect;
+};
+
+
+void print_packet(const char *label, apacket *p);
+
+asocket *find_local_socket(unsigned local_id, unsigned remote_id);
+void install_local_socket(asocket *s);
+void remove_socket(asocket *s);
+void close_all_sockets(atransport *t);
+
+#define  LOCAL_CLIENT_PREFIX  "emulator-"
+
+asocket *create_local_socket(int fd);
+asocket *create_local_service_socket(const char *destination);
+
+asocket *create_remote_socket(unsigned id, atransport *t);
+void connect_to_remote(asocket *s, const char *destination);
+void connect_to_smartsocket(asocket *s);
+
+void fatal(const char *fmt, ...);
+void fatal_errno(const char *fmt, ...);
+
+void handle_packet(apacket *p, atransport *t);
+void send_packet(apacket *p, atransport *t);
+
+void get_my_path(char *s, size_t maxLen);
+int launch_server(int server_port);
+int adb_main(int is_daemon, int server_port);
+
+
+/* transports are ref-counted
+** get_device_transport does an acquire on your behalf before returning
+*/
+void init_transport_registration(void);
+int  list_transports(char *buf, size_t  bufsize, int long_listing);
+void update_transports(void);
+
+asocket*  create_device_tracker(void);
+
+/* Obtain a transport from the available transports.
+** If state is != CS_ANY, only transports in that state are considered.
+** If serial is non-NULL then only the device with that serial will be chosen.
+** If no suitable transport is found, error is set.
+*/
+atransport *acquire_one_transport(int state, transport_type ttype, const char* serial, char **error_out);
+void   add_transport_disconnect( atransport*  t, adisconnect*  dis );
+void   remove_transport_disconnect( atransport*  t, adisconnect*  dis );
+void   run_transport_disconnects( atransport*  t );
+void   kick_transport( atransport*  t );
+
+/* initialize a transport object's func pointers and state */
+#if ADB_HOST
+int get_available_local_transport_index();
+#endif
+int  init_socket_transport(atransport *t, int s, int port, int local);
+void init_usb_transport(atransport *t, usb_handle *usb, int state);
+
+/* for MacOS X cleanup */
+void close_usb_devices();
+
+/* cause new transports to be init'd and added to the list */
+int register_socket_transport(int s, const char *serial, int port, int local);
+
+/* these should only be used for the "adb disconnect" command */
+void unregister_transport(atransport *t);
+void unregister_all_tcp_transports();
+
+void register_usb_transport(usb_handle *h, const char *serial, const char *devpath, unsigned writeable);
+
+/* this should only be used for transports with connection_state == CS_NOPERM */
+void unregister_usb_transport(usb_handle *usb);
+
+atransport *find_transport(const char *serial);
+#if ADB_HOST
+atransport* find_emulator_transport_by_adb_port(int adb_port);
+#endif
+
+int service_to_fd(const char *name);
+#if ADB_HOST
+asocket *host_service_to_socket(const char*  name, const char *serial);
+#endif
+
+#if !ADB_HOST
+int       init_jdwp(void);
+asocket*  create_jdwp_service_socket();
+asocket*  create_jdwp_tracker_service_socket();
+int       create_jdwp_connection_fd(int  jdwp_pid);
+#endif
+
+int handle_forward_request(const char* service, transport_type ttype, char* serial, int reply_fd);
+
+#if !ADB_HOST
+void framebuffer_service(int fd, void *cookie);
+void remount_service(int fd, void *cookie);
+#endif
+
+/* packet allocator */
+apacket *get_apacket(void);
+void put_apacket(apacket *p);
+
+int check_header(apacket *p);
+int check_data(apacket *p);
+
+/* define ADB_TRACE to 1 to enable tracing support, or 0 to disable it */
+
+#define  ADB_TRACE    1
+
+/* IMPORTANT: if you change the following list, don't
+ * forget to update the corresponding 'tags' table in
+ * the adb_trace_init() function implemented in adb.c
+ */
+typedef enum {
+    TRACE_ADB = 0,   /* 0x001 */
+    TRACE_SOCKETS,
+    TRACE_PACKETS,
+    TRACE_TRANSPORT,
+    TRACE_RWX,       /* 0x010 */
+    TRACE_USB,
+    TRACE_SYNC,
+    TRACE_SYSDEPS,
+    TRACE_JDWP,      /* 0x100 */
+    TRACE_SERVICES,
+    TRACE_AUTH,
+} AdbTrace;
+
+#if ADB_TRACE
+
+#if !ADB_HOST
+/*
+ * When running inside the emulator, guest's adbd can connect to 'adb-debug'
+ * qemud service that can display adb trace messages (on condition that emulator
+ * has been started with '-debug adb' option).
+ */
+
+/* Delivers a trace message to the emulator via QEMU pipe. */
+void adb_qemu_trace(const char* fmt, ...);
+/* Macro to use to send ADB trace messages to the emulator. */
+#define DQ(...)    adb_qemu_trace(__VA_ARGS__)
+#else
+#define DQ(...) ((void)0)
+#endif  /* !ADB_HOST */
+
+  extern int     adb_trace_mask;
+  extern unsigned char    adb_trace_output_count;
+  void    adb_trace_init(void);
+
+#  define ADB_TRACING  ((adb_trace_mask & (1 << TRACE_TAG)) != 0)
+
+  /* you must define TRACE_TAG before using this macro */
+#  define  D(...)                                      \
+        do {                                           \
+            if (ADB_TRACING) {                         \
+                int save_errno = errno;                \
+                adb_mutex_lock(&D_lock);               \
+                fprintf(stderr, "%s::%s():",           \
+                        __FILE__, __FUNCTION__);       \
+                errno = save_errno;                    \
+                fprintf(stderr, __VA_ARGS__ );         \
+                fflush(stderr);                        \
+                adb_mutex_unlock(&D_lock);             \
+                errno = save_errno;                    \
+           }                                           \
+        } while (0)
+#  define  DR(...)                                     \
+        do {                                           \
+            if (ADB_TRACING) {                         \
+                int save_errno = errno;                \
+                adb_mutex_lock(&D_lock);               \
+                errno = save_errno;                    \
+                fprintf(stderr, __VA_ARGS__ );         \
+                fflush(stderr);                        \
+                adb_mutex_unlock(&D_lock);             \
+                errno = save_errno;                    \
+           }                                           \
+        } while (0)
+#else
+#  define  D(...)          ((void)0)
+#  define  DR(...)         ((void)0)
+#  define  ADB_TRACING     0
+#endif /* ADB_TRACE */
+
+
+#if !DEBUG_PACKETS
+#define print_packet(tag,p) do {} while (0)
+#endif
+
+#if ADB_HOST_ON_TARGET
+/* adb and adbd are coexisting on the target, so use 5038 for adb
+ * to avoid conflicting with adbd's usage of 5037
+ */
+#  define DEFAULT_ADB_PORT 5038
+#else
+#  define DEFAULT_ADB_PORT 5037
+#endif
+
+#define DEFAULT_ADB_LOCAL_TRANSPORT_PORT 5555
+
+#define ADB_CLASS              0xff
+#define ADB_SUBCLASS           0x42
+#define ADB_PROTOCOL           0x1
+
+
+void local_init(int port);
+int  local_connect(int  port);
+int  local_connect_arbitrary_ports(int console_port, int adb_port);
+
+/* usb host/client interface */
+void usb_init();
+void usb_cleanup();
+int usb_write(usb_handle *h, const void *data, int len);
+int usb_read(usb_handle *h, void *data, int len);
+int usb_close(usb_handle *h);
+void usb_kick(usb_handle *h);
+
+/* used for USB device detection */
+#if ADB_HOST
+int is_adb_interface(int vid, int pid, int usb_class, int usb_subclass, int usb_protocol);
+#endif
+
+unsigned host_to_le32(unsigned n);
+int adb_commandline(int argc, char **argv);
+
+int connection_state(atransport *t);
+
+#define CS_ANY       -1
+#define CS_OFFLINE    0
+#define CS_BOOTLOADER 1
+#define CS_DEVICE     2
+#define CS_HOST       3
+#define CS_RECOVERY   4
+#define CS_NOPERM     5 /* Insufficient permissions to communicate with the device */
+#define CS_SIDELOAD   6
+#define CS_UNAUTHORIZED 7
+
+extern int HOST;
+extern int SHELL_EXIT_NOTIFY_FD;
+
+typedef enum {
+    SUBPROC_PTY = 0,
+    SUBPROC_RAW = 1,
+} subproc_mode;
+
+#define CHUNK_SIZE (64*1024)
+
+#if !ADB_HOST
+#define USB_ADB_PATH     "/dev/android_adb"
+
+#define USB_FFS_ADB_PATH  "/dev/usb-ffs/adb/"
+#define USB_FFS_ADB_EP(x) USB_FFS_ADB_PATH#x
+
+#define USB_FFS_ADB_EP0   USB_FFS_ADB_EP(ep0)
+#define USB_FFS_ADB_OUT   USB_FFS_ADB_EP(ep1)
+#define USB_FFS_ADB_IN    USB_FFS_ADB_EP(ep2)
+#endif
+
+int sendfailmsg(int fd, const char *reason);
+int handle_host_request(char *service, transport_type ttype, char* serial, int reply_fd, asocket *s);
+
+#endif
diff --git a/package/utils/adbd/src/adb/adb_auth.h b/package/utils/adbd/src/adb/adb_auth.h
new file mode 100644
index 0000000..b24c674
--- /dev/null
+++ b/package/utils/adbd/src/adb/adb_auth.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2012 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_AUTH_H
+#define __ADB_AUTH_H
+
+void adb_auth_init(void);
+void adb_auth_verified(atransport *t);
+
+void send_auth_request(atransport *t);
+
+/* AUTH packets first argument */
+/* Request */
+#define ADB_AUTH_TOKEN         1
+/* Response */
+#define ADB_AUTH_SIGNATURE     2
+#define ADB_AUTH_RSAPUBLICKEY  3
+
+#if ADB_HOST
+
+int adb_auth_sign(void *key, void *token, size_t token_size, void *sig);
+void *adb_auth_nextkey(void *current);
+int adb_auth_get_userkey(unsigned char *data, size_t len);
+
+static inline int adb_auth_generate_token(void *token, size_t token_size) { return 0; }
+static inline int adb_auth_verify(void *token, void *sig, int siglen) { return 0; }
+static inline void adb_auth_confirm_key(unsigned char *data, size_t len, atransport *t) { }
+
+#else // !ADB_HOST
+
+static inline int adb_auth_sign(void* key, void *token, size_t token_size, void *sig) { return 0; }
+static inline void *adb_auth_nextkey(void *current) { return NULL; }
+static inline int adb_auth_get_userkey(unsigned char *data, size_t len) { return 0; }
+
+int adb_auth_generate_token(void *token, size_t token_size);
+int adb_auth_verify(void *token, void *sig, int siglen);
+void adb_auth_confirm_key(unsigned char *data, size_t len, atransport *t);
+
+#endif // ADB_HOST
+
+#endif // __ADB_AUTH_H
diff --git a/package/utils/adbd/src/adb/adb_auth_client.c b/package/utils/adbd/src/adb/adb_auth_client.c
new file mode 100644
index 0000000..26ecc3c
--- /dev/null
+++ b/package/utils/adbd/src/adb/adb_auth_client.c
@@ -0,0 +1,270 @@
+/*
+ * Copyright (C) 2012 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 <string.h>
+//#include <resolv.h>
+#include <cutils/list.h>
+#include <cutils/sockets.h>
+
+#include "sysdeps.h"
+#include "adb.h"
+#include "adb_auth.h"
+#include "fdevent.h"
+#include "mincrypt/rsa.h"
+#include "mincrypt/sha.h"
+
+#define TRACE_TAG TRACE_AUTH
+
+
+struct adb_public_key {
+    struct listnode node;
+    RSAPublicKey key;
+};
+
+static char *key_paths[] = {
+    "/adb_keys",
+    "/data/misc/adb/adb_keys",
+    NULL
+};
+
+static fdevent listener_fde;
+static int framework_fd = -1;
+
+static void usb_disconnected(void* unused, atransport* t);
+static struct adisconnect usb_disconnect = { usb_disconnected, 0, 0, 0 };
+static atransport* usb_transport;
+static bool needs_retry = false;
+
+extern int b64_pton(const char *src, unsigned char *dst, int dstsiz);
+static void read_keys(const char *file, struct listnode *list)
+{
+    struct adb_public_key *key;
+    FILE *f;
+    char buf[MAX_PAYLOAD];
+    char *sep;
+    int ret;
+
+    f = fopen(file, "r");
+    if (!f) {
+        D("Can't open '%s'\n", file);
+        return;
+    }
+
+    while (fgets(buf, sizeof(buf), f)) {
+        /* Allocate 4 extra bytes to decode the base64 data in-place */
+        key = calloc(1, sizeof(*key) + 4);
+        if (!key) {
+            D("Can't malloc key\n");
+            break;
+        }
+
+        sep = strpbrk(buf, " \t");
+        if (sep)
+            *sep = '\0';
+
+        ret = b64_pton(buf, (u_char *)&key->key, sizeof(key->key) + 4);
+        if (ret != sizeof(key->key)) {
+            D("%s: Invalid base64 data ret=%d\n", file, ret);
+            free(key);
+            continue;
+        }
+
+        if (key->key.len != RSANUMWORDS) {
+            D("%s: Invalid key len %d\n", file, key->key.len);
+            free(key);
+            continue;
+        }
+
+        list_add_tail(list, &key->node);
+    }
+
+    fclose(f);
+}
+
+static void free_keys(struct listnode *list)
+{
+    struct listnode *item;
+
+    while (!list_empty(list)) {
+        item = list_head(list);
+        list_remove(item);
+        free(node_to_item(item, struct adb_public_key, node));
+    }
+}
+
+static void load_keys(struct listnode *list)
+{
+    char *path;
+    char **paths = key_paths;
+    struct stat buf;
+
+    list_init(list);
+
+    while ((path = *paths++)) {
+        if (!stat(path, &buf)) {
+            D("Loading keys from '%s'\n", path);
+            read_keys(path, list);
+        }
+    }
+}
+
+int adb_auth_generate_token(void *token, size_t token_size)
+{
+    FILE *f;
+    int ret;
+
+    f = fopen("/dev/urandom", "r");
+    if (!f)
+        return 0;
+
+    ret = fread(token, token_size, 1, f);
+
+    fclose(f);
+    return ret * token_size;
+}
+
+int adb_auth_verify(void *token, void *sig, int siglen)
+{
+    struct listnode *item;
+    struct adb_public_key *key;
+    struct listnode key_list;
+    int ret = 0;
+
+    if (siglen != RSANUMBYTES)
+        return 0;
+
+    load_keys(&key_list);
+
+    list_for_each(item, &key_list) {
+        key = node_to_item(item, struct adb_public_key, node);
+        ret = RSA_verify(&key->key, sig, siglen, token, SHA_DIGEST_SIZE);
+        if (ret)
+            break;
+    }
+
+    free_keys(&key_list);
+
+    return ret;
+}
+
+static void usb_disconnected(void* unused, atransport* t)
+{
+    D("USB disconnect\n");
+    remove_transport_disconnect(usb_transport, &usb_disconnect);
+    usb_transport = NULL;
+    needs_retry = false;
+}
+
+static void adb_auth_event(int fd, unsigned events, void *data)
+{
+    char response[2];
+    int ret;
+
+    if (events & FDE_READ) {
+        ret = unix_read(fd, response, sizeof(response));
+        if (ret < 0) {
+            D("Framework disconnect\n");
+            if (usb_transport)
+                fdevent_remove(&usb_transport->auth_fde);
+            framework_fd = -1;
+        }
+        else if (ret == 2 && response[0] == 'O' && response[1] == 'K') {
+            if (usb_transport)
+                adb_auth_verified(usb_transport);
+        }
+    }
+}
+
+void adb_auth_confirm_key(unsigned char *key, size_t len, atransport *t)
+{
+    char msg[MAX_PAYLOAD];
+    int ret;
+
+    if (!usb_transport) {
+        usb_transport = t;
+        add_transport_disconnect(t, &usb_disconnect);
+    }
+
+    if (framework_fd < 0) {
+        D("Client not connected\n");
+        needs_retry = true;
+        return;
+    }
+
+    if (key[len - 1] != '\0') {
+        D("Key must be a null-terminated string\n");
+        return;
+    }
+
+    ret = snprintf(msg, sizeof(msg), "PK%s", key);
+    if (ret >= (signed)sizeof(msg)) {
+        D("Key too long. ret=%d", ret);
+        return;
+    }
+    D("Sending '%s'\n", msg);
+
+    ret = unix_write(framework_fd, msg, ret);
+    if (ret < 0) {
+        D("Failed to write PK, errno=%d\n", errno);
+        return;
+    }
+
+    fdevent_install(&t->auth_fde, framework_fd, adb_auth_event, t);
+    fdevent_add(&t->auth_fde, FDE_READ);
+}
+
+static void adb_auth_listener(int fd, unsigned events, void *data)
+{
+    struct sockaddr addr;
+    socklen_t alen;
+    int s;
+
+    alen = sizeof(addr);
+
+    s = adb_socket_accept(fd, &addr, &alen);
+    if (s < 0) {
+        D("Failed to accept: errno=%d\n", errno);
+        return;
+    }
+
+    framework_fd = s;
+
+    if (needs_retry) {
+        needs_retry = false;
+        send_auth_request(usb_transport);
+    }
+}
+
+void adb_auth_init(void)
+{
+    int fd, ret;
+
+    fd = android_get_control_socket("adbd");
+    if (fd < 0) {
+        D("Failed to get adbd socket\n");
+        return;
+    }
+
+    ret = listen(fd, 4);
+    if (ret < 0) {
+        D("Failed to listen on '%d'\n", fd);
+        return;
+    }
+
+    fdevent_install(&listener_fde, fd, adb_auth_listener, NULL);
+    fdevent_add(&listener_fde, FDE_READ);
+}
diff --git a/package/utils/adbd/src/adb/adb_auth_host.c b/package/utils/adbd/src/adb/adb_auth_host.c
new file mode 100644
index 0000000..974d08c
--- /dev/null
+++ b/package/utils/adbd/src/adb/adb_auth_host.c
@@ -0,0 +1,426 @@
+/*
+ * Copyright (C) 2012 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>
+
+#ifdef _WIN32
+#  define WIN32_LEAN_AND_MEAN
+#  include "windows.h"
+#  include "shlobj.h"
+#else
+#  include <sys/types.h>
+#  include <sys/stat.h>
+#  include <unistd.h>
+#endif
+#include <string.h>
+
+#include "sysdeps.h"
+#include "adb.h"
+#include "adb_auth.h"
+
+/* HACK: we need the RSAPublicKey struct
+ * but RSA_verify conflits with openssl */
+#define RSA_verify RSA_verify_mincrypt
+#include "mincrypt/rsa.h"
+#undef RSA_verify
+
+#include <cutils/list.h>
+#if 0
+#include <openssl/evp.h>
+#include <openssl/objects.h>
+#include <openssl/pem.h>
+#include <openssl/rsa.h>
+#include <openssl/sha.h>
+#endif
+#define TRACE_TAG TRACE_AUTH
+
+#define ANDROID_PATH   ".android"
+#define ADB_KEY_FILE   "adbkey"
+
+
+struct adb_private_key {
+    struct listnode node;
+    RSA *rsa;
+};
+
+static struct listnode key_list;
+
+
+/* Convert OpenSSL RSA private key to android pre-computed RSAPublicKey format */
+static int RSA_to_RSAPublicKey(RSA *rsa, RSAPublicKey *pkey)
+{
+    int ret = 1;
+    unsigned int i;
+
+    BN_CTX* ctx = BN_CTX_new();
+    BIGNUM* r32 = BN_new();
+    BIGNUM* rr = BN_new();
+    BIGNUM* r = BN_new();
+    BIGNUM* rem = BN_new();
+    BIGNUM* n = BN_new();
+    BIGNUM* n0inv = BN_new();
+
+    if (RSA_size(rsa) != RSANUMBYTES) {
+        ret = 0;
+        goto out;
+    }
+
+    BN_set_bit(r32, 32);
+    BN_copy(n, rsa->n);
+    BN_set_bit(r, RSANUMWORDS * 32);
+    BN_mod_sqr(rr, r, n, ctx);
+    BN_div(NULL, rem, n, r32, ctx);
+    BN_mod_inverse(n0inv, rem, r32, ctx);
+
+    pkey->len = RSANUMWORDS;
+    pkey->n0inv = 0 - BN_get_word(n0inv);
+    for (i = 0; i < RSANUMWORDS; i++) {
+        BN_div(rr, rem, rr, r32, ctx);
+        pkey->rr[i] = BN_get_word(rem);
+        BN_div(n, rem, n, r32, ctx);
+        pkey->n[i] = BN_get_word(rem);
+    }
+    pkey->exponent = BN_get_word(rsa->e);
+
+out:
+    BN_free(n0inv);
+    BN_free(n);
+    BN_free(rem);
+    BN_free(r);
+    BN_free(rr);
+    BN_free(r32);
+    BN_CTX_free(ctx);
+
+    return ret;
+}
+
+static void get_user_info(char *buf, size_t len)
+{
+    char hostname[1024], username[1024];
+    int ret;
+
+#ifndef _WIN32
+    ret = gethostname(hostname, sizeof(hostname));
+    if (ret < 0)
+#endif
+        strcpy(hostname, "unknown");
+
+#if !defined _WIN32 && !defined ADB_HOST_ON_TARGET
+    ret = getlogin_r(username, sizeof(username));
+    if (ret < 0)
+#endif
+        strcpy(username, "unknown");
+
+    ret = snprintf(buf, len, " %s@%s", username, hostname);
+    if (ret >= (signed)len)
+        buf[len - 1] = '\0';
+}
+
+static int write_public_keyfile(RSA *private_key, const char *private_key_path)
+{
+    RSAPublicKey pkey;
+    BIO *bio, *b64, *bfile;
+    char path[PATH_MAX], info[MAX_PAYLOAD];
+    int ret;
+
+    ret = snprintf(path, sizeof(path), "%s.pub", private_key_path);
+    if (ret >= (signed)sizeof(path))
+        return 0;
+
+    ret = RSA_to_RSAPublicKey(private_key, &pkey);
+    if (!ret) {
+        D("Failed to convert to publickey\n");
+        return 0;
+    }
+
+    bfile = BIO_new_file(path, "w");
+    if (!bfile) {
+        D("Failed to open '%s'\n", path);
+        return 0;
+    }
+
+    D("Writing public key to '%s'\n", path);
+
+    b64 = BIO_new(BIO_f_base64());
+    BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
+
+    bio = BIO_push(b64, bfile);
+    BIO_write(bio, &pkey, sizeof(pkey));
+    (void) BIO_flush(bio);
+    BIO_pop(b64);
+    BIO_free(b64);
+
+    get_user_info(info, sizeof(info));
+    BIO_write(bfile, info, strlen(info));
+    (void) BIO_flush(bfile);
+    BIO_free_all(bfile);
+
+    return 1;
+}
+
+static int generate_key(const char *file)
+{
+    EVP_PKEY* pkey = EVP_PKEY_new();
+    BIGNUM* exponent = BN_new();
+    RSA* rsa = RSA_new();
+    mode_t old_mask;
+    FILE *f = NULL;
+    int ret = 0;
+
+    D("generate_key '%s'\n", file);
+
+    if (!pkey || !exponent || !rsa) {
+        D("Failed to allocate key\n");
+        goto out;
+    }
+
+    BN_set_word(exponent, RSA_F4);
+    RSA_generate_key_ex(rsa, 2048, exponent, NULL);
+    EVP_PKEY_set1_RSA(pkey, rsa);
+
+    old_mask = umask(077);
+
+    f = fopen(file, "w");
+    if (!f) {
+        D("Failed to open '%s'\n", file);
+        umask(old_mask);
+        goto out;
+    }
+
+    umask(old_mask);
+
+    if (!PEM_write_PrivateKey(f, pkey, NULL, NULL, 0, NULL, NULL)) {
+        D("Failed to write key\n");
+        goto out;
+    }
+
+    if (!write_public_keyfile(rsa, file)) {
+        D("Failed to write public key\n");
+        goto out;
+    }
+
+    ret = 1;
+
+out:
+    if (f)
+        fclose(f);
+    EVP_PKEY_free(pkey);
+    RSA_free(rsa);
+    BN_free(exponent);
+    return ret;
+}
+
+static int read_key(const char *file, struct listnode *list)
+{
+    struct adb_private_key *key;
+    FILE *f;
+
+    D("read_key '%s'\n", file);
+
+    f = fopen(file, "r");
+    if (!f) {
+        D("Failed to open '%s'\n", file);
+        return 0;
+    }
+
+    key = malloc(sizeof(*key));
+    if (!key) {
+        D("Failed to alloc key\n");
+        fclose(f);
+        return 0;
+    }
+    key->rsa = RSA_new();
+
+    if (!PEM_read_RSAPrivateKey(f, &key->rsa, NULL, NULL)) {
+        D("Failed to read key\n");
+        fclose(f);
+        RSA_free(key->rsa);
+        free(key);
+        return 0;
+    }
+
+    fclose(f);
+    list_add_tail(list, &key->node);
+    return 1;
+}
+
+static int get_user_keyfilepath(char *filename, size_t len)
+{
+    const char *format, *home;
+    char android_dir[PATH_MAX];
+    struct stat buf;
+#ifdef _WIN32
+    char path[PATH_MAX];
+    home = getenv("ANDROID_SDK_HOME");
+    if (!home) {
+        SHGetFolderPath(NULL, CSIDL_PROFILE, NULL, 0, path);
+        home = path;
+    }
+    format = "%s\\%s";
+#else
+    home = getenv("HOME");
+    if (!home)
+        return -1;
+    format = "%s/%s";
+#endif
+
+    D("home '%s'\n", home);
+
+    if (snprintf(android_dir, sizeof(android_dir), format, home,
+                        ANDROID_PATH) >= (int)sizeof(android_dir))
+        return -1;
+
+    if (stat(android_dir, &buf)) {
+        if (adb_mkdir(android_dir, 0750) < 0) {
+            D("Cannot mkdir '%s'", android_dir);
+            return -1;
+        }
+    }
+
+    return snprintf(filename, len, format, android_dir, ADB_KEY_FILE);
+}
+
+static int get_user_key(struct listnode *list)
+{
+    struct stat buf;
+    char path[PATH_MAX];
+    int ret;
+
+    ret = get_user_keyfilepath(path, sizeof(path));
+    if (ret < 0 || ret >= (signed)sizeof(path)) {
+        D("Error getting user key filename");
+        return 0;
+    }
+
+    D("user key '%s'\n", path);
+
+    if (stat(path, &buf) == -1) {
+        if (!generate_key(path)) {
+            D("Failed to generate new key\n");
+            return 0;
+        }
+    }
+
+    return read_key(path, list);
+}
+
+static void get_vendor_keys(struct listnode *list)
+{
+    const char *adb_keys_path;
+    char keys_path[MAX_PAYLOAD];
+    char *path;
+    char *save;
+    struct stat buf;
+
+    adb_keys_path = getenv("ADB_VENDOR_KEYS");
+    if (!adb_keys_path)
+        return;
+    strncpy(keys_path, adb_keys_path, sizeof(keys_path));
+
+    path = adb_strtok_r(keys_path, ENV_PATH_SEPARATOR_STR, &save);
+    while (path) {
+        D("Reading: '%s'\n", path);
+
+        if (stat(path, &buf))
+            D("Can't read '%s'\n", path);
+        else if (!read_key(path, list))
+            D("Failed to read '%s'\n", path);
+
+        path = adb_strtok_r(NULL, ENV_PATH_SEPARATOR_STR, &save);
+    }
+}
+
+int adb_auth_sign(void *node, void *token, size_t token_size, void *sig)
+{
+    unsigned int len;
+    struct adb_private_key *key = node_to_item(node, struct adb_private_key, node);
+
+    if (!RSA_sign(NID_sha1, token, token_size, sig, &len, key->rsa)) {
+        return 0;
+    }
+
+    D("adb_auth_sign len=%d\n", len);
+    return (int)len;
+}
+
+void *adb_auth_nextkey(void *current)
+{
+    struct listnode *item;
+
+    if (list_empty(&key_list))
+        return NULL;
+
+    if (!current)
+        return list_head(&key_list);
+
+    list_for_each(item, &key_list) {
+        if (item == current) {
+            /* current is the last item, we tried all the keys */
+            if (item->next == &key_list)
+                return NULL;
+            return item->next;
+        }
+    }
+
+    return NULL;
+}
+
+int adb_auth_get_userkey(unsigned char *data, size_t len)
+{
+    char path[PATH_MAX];
+    char *file;
+    int ret;
+
+    ret = get_user_keyfilepath(path, sizeof(path) - 4);
+    if (ret < 0 || ret >= (signed)(sizeof(path) - 4)) {
+        D("Error getting user key filename");
+        return 0;
+    }
+    strcat(path, ".pub");
+
+    file = load_file(path, (unsigned*)&ret);
+    if (!file) {
+        D("Can't load '%s'\n", path);
+        return 0;
+    }
+
+    if (len < (size_t)(ret + 1)) {
+        D("%s: Content too large ret=%d\n", path, ret);
+        return 0;
+    }
+
+    memcpy(data, file, ret);
+    data[ret] = '\0';
+
+    return ret + 1;
+}
+
+void adb_auth_init(void)
+{
+    int ret;
+
+    D("adb_auth_init\n");
+
+    list_init(&key_list);
+
+    ret = get_user_key(&key_list);
+    if (!ret) {
+        D("Failed to get user key\n");
+        return;
+    }
+
+    get_vendor_keys(&key_list);
+}
diff --git a/package/utils/adbd/src/adb/adb_client.c b/package/utils/adbd/src/adb/adb_client.c
new file mode 100644
index 0000000..1e47486
--- /dev/null
+++ b/package/utils/adbd/src/adb/adb_client.c
@@ -0,0 +1,345 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <zipfile/zipfile.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "sysdeps.h"
+
+#define  TRACE_TAG  TRACE_ADB
+#include "adb_client.h"
+
+static transport_type __adb_transport = kTransportAny;
+static const char* __adb_serial = NULL;
+
+static int __adb_server_port = DEFAULT_ADB_PORT;
+static const char* __adb_server_name = NULL;
+
+void adb_set_transport(transport_type type, const char* serial)
+{
+    __adb_transport = type;
+    __adb_serial = serial;
+}
+
+void adb_set_tcp_specifics(int server_port)
+{
+    __adb_server_port = server_port;
+}
+
+void adb_set_tcp_name(const char* hostname)
+{
+    __adb_server_name = hostname;
+}
+
+int  adb_get_emulator_console_port(void)
+{
+    const char*   serial = __adb_serial;
+    int           port;
+
+    if (serial == NULL) {
+        /* if no specific device was specified, we need to look at */
+        /* the list of connected devices, and extract an emulator  */
+        /* name from it. two emulators is an error                 */
+        char*  tmp = adb_query("host:devices");
+        char*  p   = tmp;
+        if(!tmp) {
+            printf("no emulator connected\n");
+            return -1;
+        }
+        while (*p) {
+            char*  q = strchr(p, '\n');
+            if (q != NULL)
+                *q++ = 0;
+            else
+                q = p + strlen(p);
+
+            if (!memcmp(p, LOCAL_CLIENT_PREFIX, sizeof(LOCAL_CLIENT_PREFIX)-1)) {
+                if (serial != NULL) {  /* more than one emulator listed */
+                    free(tmp);
+                    return -2;
+                }
+                serial = p;
+            }
+
+            p = q;
+        }
+        free(tmp);
+
+        if (serial == NULL)
+            return -1;  /* no emulator found */
+    }
+    else {
+        if (memcmp(serial, LOCAL_CLIENT_PREFIX, sizeof(LOCAL_CLIENT_PREFIX)-1) != 0)
+            return -1;  /* not an emulator */
+    }
+
+    serial += sizeof(LOCAL_CLIENT_PREFIX)-1;
+    port    = strtol(serial, NULL, 10);
+    return port;
+}
+
+static char __adb_error[256] = { 0 };
+
+const char *adb_error(void)
+{
+    return __adb_error;
+}
+
+static int switch_socket_transport(int fd)
+{
+    char service[64];
+    char tmp[5];
+    int len;
+
+    if (__adb_serial)
+        snprintf(service, sizeof service, "host:transport:%s", __adb_serial);
+    else {
+        char* transport_type = "???";
+
+         switch (__adb_transport) {
+            case kTransportUsb:
+                transport_type = "transport-usb";
+                break;
+            case kTransportLocal:
+                transport_type = "transport-local";
+                break;
+            case kTransportAny:
+                transport_type = "transport-any";
+                break;
+            case kTransportHost:
+                // no switch necessary
+                return 0;
+                break;
+        }
+
+        snprintf(service, sizeof service, "host:%s", transport_type);
+    }
+    len = strlen(service);
+    snprintf(tmp, sizeof tmp, "%04x", len);
+
+    if(writex(fd, tmp, 4) || writex(fd, service, len)) {
+        strcpy(__adb_error, "write failure during connection");
+        adb_close(fd);
+        return -1;
+    }
+    D("Switch transport in progress\n");
+
+    if(adb_status(fd)) {
+        adb_close(fd);
+        D("Switch transport failed\n");
+        return -1;
+    }
+    D("Switch transport success\n");
+    return 0;
+}
+
+int adb_status(int fd)
+{
+    unsigned char buf[5];
+    unsigned len;
+
+    if(readx(fd, buf, 4)) {
+        strcpy(__adb_error, "protocol fault (no status)");
+        return -1;
+    }
+
+    if(!memcmp(buf, "OKAY", 4)) {
+        return 0;
+    }
+
+    if(memcmp(buf, "FAIL", 4)) {
+        sprintf(__adb_error,
+                "protocol fault (status %02x %02x %02x %02x?!)",
+                buf[0], buf[1], buf[2], buf[3]);
+        return -1;
+    }
+
+    if(readx(fd, buf, 4)) {
+        strcpy(__adb_error, "protocol fault (status len)");
+        return -1;
+    }
+    buf[4] = 0;
+    len = strtoul((char*)buf, 0, 16);
+    if(len > 255) len = 255;
+    if(readx(fd, __adb_error, len)) {
+        strcpy(__adb_error, "protocol fault (status read)");
+        return -1;
+    }
+    __adb_error[len] = 0;
+    return -1;
+}
+
+int _adb_connect(const char *service)
+{
+    char tmp[5];
+    int len;
+    int fd;
+
+    D("_adb_connect: %s\n", service);
+    len = strlen(service);
+    if((len < 1) || (len > 1024)) {
+        strcpy(__adb_error, "service name too long");
+        return -1;
+    }
+    snprintf(tmp, sizeof tmp, "%04x", len);
+
+    if (__adb_server_name)
+        fd = socket_network_client(__adb_server_name, __adb_server_port, SOCK_STREAM);
+    else
+        fd = socket_loopback_client(__adb_server_port, SOCK_STREAM);
+
+    if(fd < 0) {
+        strcpy(__adb_error, "cannot connect to daemon");
+        return -2;
+    }
+
+    if (memcmp(service,"host",4) != 0 && switch_socket_transport(fd)) {
+        return -1;
+    }
+
+    if(writex(fd, tmp, 4) || writex(fd, service, len)) {
+        strcpy(__adb_error, "write failure during connection");
+        adb_close(fd);
+        return -1;
+    }
+
+    if(adb_status(fd)) {
+        adb_close(fd);
+        return -1;
+    }
+
+    D("_adb_connect: return fd %d\n", fd);
+    return fd;
+}
+
+int adb_connect(const char *service)
+{
+    // first query the adb server's version
+    int fd = _adb_connect("host:version");
+
+    D("adb_connect: service %s\n", service);
+    if(fd == -2 && __adb_server_name) {
+        fprintf(stderr,"** Cannot start server on remote host\n");
+        return fd;
+    } else if(fd == -2) {
+        fprintf(stdout,"* daemon not running. starting it now on port %d *\n",
+                __adb_server_port);
+    start_server:
+        if(launch_server(__adb_server_port)) {
+            fprintf(stderr,"* failed to start daemon *\n");
+            return -1;
+        } else {
+            fprintf(stdout,"* daemon started successfully *\n");
+        }
+        /* give the server some time to start properly and detect devices */
+        adb_sleep_ms(3000);
+        // fall through to _adb_connect
+    } else {
+        // if server was running, check its version to make sure it is not out of date
+        char buf[100];
+        size_t n;
+        int version = ADB_SERVER_VERSION - 1;
+
+        // if we have a file descriptor, then parse version result
+        if(fd >= 0) {
+            if(readx(fd, buf, 4)) goto error;
+
+            buf[4] = 0;
+            n = strtoul(buf, 0, 16);
+            if(n > sizeof(buf)) goto error;
+            if(readx(fd, buf, n)) goto error;
+            adb_close(fd);
+
+            if (sscanf(buf, "%04x", &version) != 1) goto error;
+        } else {
+            // if fd is -1, then check for "unknown host service",
+            // which would indicate a version of adb that does not support the version command
+            if (strcmp(__adb_error, "unknown host service") != 0)
+                return fd;
+        }
+
+        if(version != ADB_SERVER_VERSION) {
+            printf("adb server is out of date.  killing...\n");
+            fd = _adb_connect("host:kill");
+            adb_close(fd);
+
+            /* XXX can we better detect its death? */
+            adb_sleep_ms(2000);
+            goto start_server;
+        }
+    }
+
+    // if the command is start-server, we are done.
+    if (!strcmp(service, "host:start-server"))
+        return 0;
+
+    fd = _adb_connect(service);
+    if(fd == -1) {
+        fprintf(stderr,"error: %s\n", __adb_error);
+    } else if(fd == -2) {
+        fprintf(stderr,"** daemon still not running\n");
+    }
+    D("adb_connect: return fd %d\n", fd);
+
+    return fd;
+error:
+    adb_close(fd);
+    return -1;
+}
+
+
+int adb_command(const char *service)
+{
+    int fd = adb_connect(service);
+    if(fd < 0) {
+        return -1;
+    }
+
+    if(adb_status(fd)) {
+        adb_close(fd);
+        return -1;
+    }
+
+    return 0;
+}
+
+char *adb_query(const char *service)
+{
+    char buf[5];
+    unsigned n;
+    char *tmp;
+
+    D("adb_query: %s\n", service);
+    int fd = adb_connect(service);
+    if(fd < 0) {
+        fprintf(stderr,"error: %s\n", __adb_error);
+        return 0;
+    }
+
+    if(readx(fd, buf, 4)) goto oops;
+
+    buf[4] = 0;
+    n = strtoul(buf, 0, 16);
+    if(n >= 0xffff) {
+        strcpy(__adb_error, "reply is too long (>= 64kB)");
+        goto oops;
+    }
+
+    tmp = malloc(n + 1);
+    if(tmp == 0) goto oops;
+
+    if(readx(fd, tmp, n) == 0) {
+        tmp[n] = 0;
+        adb_close(fd);
+        return tmp;
+    }
+    free(tmp);
+
+oops:
+    adb_close(fd);
+    return 0;
+}
diff --git a/package/utils/adbd/src/adb/adb_client.h b/package/utils/adbd/src/adb/adb_client.h
new file mode 100644
index 0000000..0ec47ca
--- /dev/null
+++ b/package/utils/adbd/src/adb/adb_client.h
@@ -0,0 +1,57 @@
+#ifndef _ADB_CLIENT_H_
+#define _ADB_CLIENT_H_
+
+#include "adb.h"
+
+/* connect to adb, connect to the named service, and return
+** a valid fd for interacting with that service upon success
+** or a negative number on failure
+*/
+int adb_connect(const char *service);
+int _adb_connect(const char *service);
+
+/* connect to adb, connect to the named service, return 0 if
+** the connection succeeded AND the service returned OKAY
+*/
+int adb_command(const char *service);
+
+/* connect to adb, connect to the named service, return
+** a malloc'd string of its response upon success or NULL
+** on failure.
+*/
+char *adb_query(const char *service);
+
+/* Set the preferred transport to connect to.
+*/
+void adb_set_transport(transport_type type, const char* serial);
+
+/* Set TCP specifics of the transport to use
+*/
+void adb_set_tcp_specifics(int server_port);
+
+/* Set TCP Hostname of the transport to use
+*/
+void adb_set_tcp_name(const char* hostname);
+
+/* Return the console port of the currently connected emulator (if any)
+ * of -1 if there is no emulator, and -2 if there is more than one.
+ * assumes adb_set_transport() was alled previously...
+ */
+int  adb_get_emulator_console_port(void);
+
+/* send commands to the current emulator instance. will fail if there
+ * is zero, or more than one emulator connected (or if you use -s <serial>
+ * with a <serial> that does not designate an emulator)
+ */
+int  adb_send_emulator_command(int  argc, char**  argv);
+
+/* return verbose error string from last operation */
+const char *adb_error(void);
+
+/* read a standard adb status response (OKAY|FAIL) and
+** return 0 in the event of OKAY, -1 in the event of FAIL
+** or protocol error
+*/
+int adb_status(int fd);
+
+#endif
diff --git a/package/utils/adbd/src/adb/b64_pton.c b/package/utils/adbd/src/adb/b64_pton.c
new file mode 100644
index 0000000..4ce2f4d
--- /dev/null
+++ b/package/utils/adbd/src/adb/b64_pton.c
@@ -0,0 +1,56 @@
+
+#include <ctype.h>
+
+int b64_pton(const char *src, unsigned char *dst, int dstsiz)
+{
+    int i, j, k;
+    unsigned int val3 = 0;
+    const char b64_tbl[] =
+        "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
+        "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
+        "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x3e\xff\xff\xff\x3f"
+        "\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\xff\xff\xff\x00\xff\xff"
+        "\xff\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e"
+        "\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\xff\xff\xff\xff\xff"
+        "\xff\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28"
+        "\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\xff\xff\xff\xff\xff"
+        "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
+        "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
+        "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
+        "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
+        "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
+        "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
+        "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
+        "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff";
+
+    for (i = j = k = 0; src[i] != '\0'; i++) {
+        if (isspace(src[i]))
+            continue;
+        if (b64_tbl[(unsigned char)src[i]] == (char)0xff)
+            return(-1);
+        val3 |= b64_tbl[(unsigned char)src[i]];
+        if (src[i] != '=') {
+            if (dst != 0 && k >= dstsiz)
+                return (-1);
+            if (j % 4 == 1) {
+                if (dst != 0)
+                    dst[k] = val3 >> 4;
+                k++;
+            } else if (j % 4 == 2) {
+                if (dst != 0)
+                    dst[k] = val3 >> 2;
+                k++;
+            } else if (j % 4 == 3) {
+                if (dst != 0)
+                    dst[k] = val3;
+                k++;
+            }
+        }
+        val3 <<= 6;
+        j++;
+    }
+    if (j % 4 != 0)
+        return (-1);
+
+    return (k);
+}
diff --git a/package/utils/adbd/src/adb/commandline.c b/package/utils/adbd/src/adb/commandline.c
new file mode 100644
index 0000000..507f73e
--- /dev/null
+++ b/package/utils/adbd/src/adb/commandline.c
@@ -0,0 +1,1851 @@
+/*
+ * 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 <errno.h>
+#include <unistd.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include <assert.h>
+
+#include "sysdeps.h"
+
+#ifdef HAVE_TERMIO_H
+#include <termios.h>
+#endif
+
+#define  TRACE_TAG  TRACE_ADB
+#include "adb.h"
+#include "adb_client.h"
+#include "file_sync_service.h"
+
+static int do_cmd(transport_type ttype, char* serial, char *cmd, ...);
+
+void get_my_path(char *s, size_t maxLen);
+int find_sync_dirs(const char *srcarg,
+        char **android_srcdir_out, char **data_srcdir_out);
+int install_app(transport_type transport, char* serial, int argc, char** argv);
+int uninstall_app(transport_type transport, char* serial, int argc, char** argv);
+
+static const char *gProductOutPath = NULL;
+extern int gListenAll;
+
+static char *product_file(const char *extra)
+{
+    int n;
+    char *x;
+
+    if (gProductOutPath == NULL) {
+        fprintf(stderr, "adb: Product directory not specified; "
+                "use -p or define ANDROID_PRODUCT_OUT\n");
+        exit(1);
+    }
+
+    n = strlen(gProductOutPath) + strlen(extra) + 2;
+    x = malloc(n);
+    if (x == 0) {
+        fprintf(stderr, "adb: Out of memory (product_file())\n");
+        exit(1);
+    }
+
+    snprintf(x, (size_t)n, "%s" OS_PATH_SEPARATOR_STR "%s", gProductOutPath, extra);
+    return x;
+}
+
+void version(FILE * out) {
+    fprintf(out, "Android Debug Bridge version %d.%d.%d\n",
+         ADB_VERSION_MAJOR, ADB_VERSION_MINOR, ADB_SERVER_VERSION);
+}
+
+void help()
+{
+    version(stderr);
+
+    fprintf(stderr,
+        "\n"
+        " -a                            - directs adb to listen on all interfaces for a connection\n"
+        " -d                            - directs command to the only connected USB device\n"
+        "                                 returns an error if more than one USB device is present.\n"
+        " -e                            - directs command to the only running emulator.\n"
+        "                                 returns an error if more than one emulator is running.\n"
+        " -s <specific device>          - directs command to the device or emulator with the given\n"
+        "                                 serial number or qualifier. Overrides ANDROID_SERIAL\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"
+        "                                 If -p is not specified, the ANDROID_PRODUCT_OUT\n"
+        "                                 environment variable is used, which must\n"
+        "                                 be an absolute path.\n"
+        " -H                            - Name of adb server host (default: localhost)\n"
+        " -P                            - Port of adb server (default: 5037)\n"
+        " devices [-l]                  - list all connected devices\n"
+        "                                 ('-l' will also list device qualifiers)\n"
+        " connect <host>[:<port>]       - connect to a device via TCP/IP\n"
+        "                                 Port 5555 is used by default if no port number is specified.\n"
+        " disconnect [<host>[:<port>]]  - disconnect from a TCP/IP device.\n"
+        "                                 Port 5555 is used by default if no port number is specified.\n"
+        "                                 Using this command with no additional arguments\n"
+        "                                 will disconnect from all connected TCP/IP devices.\n"
+        "\n"
+        "device commands:\n"
+        "  adb push [-p] <local> <remote>\n"
+        "                               - copy file/dir to device\n"
+        "                                 ('-p' to display the transfer progress)\n"
+        "  adb pull [-p] [-a] <remote> [<local>]\n"
+        "                               - copy file/dir from device\n"
+        "                                 ('-p' to display the transfer progress)\n"
+        "                                 ('-a' means copy timestamp and mode)\n"
+        "  adb sync [ <directory> ]     - copy host->device only if changed\n"
+        "                                 (-l means list but don't copy)\n"
+        "                                 (see 'adb help all')\n"
+        "  adb shell                    - run remote shell interactively\n"
+        "  adb shell <command>          - run remote shell command\n"
+        "  adb emu <command>            - run emulator console command\n"
+        "  adb logcat [ <filter-spec> ] - View device log\n"
+        "  adb forward --list           - list all forward socket connections.\n"
+        "                                 the format is a list of lines with the following format:\n"
+        "                                    <serial> \" \" <local> \" \" <remote> \"\\n\"\n"
+        "  adb forward <local> <remote> - forward socket connections\n"
+        "                                 forward specs are one of: \n"
+        "                                   tcp:<port>\n"
+        "                                   localabstract:<unix domain socket name>\n"
+        "                                   localreserved:<unix domain socket name>\n"
+        "                                   localfilesystem:<unix domain socket name>\n"
+        "                                   dev:<character device name>\n"
+        "                                   jdwp:<process pid> (remote only)\n"
+        "  adb forward --no-rebind <local> <remote>\n"
+        "                               - same as 'adb forward <local> <remote>' but fails\n"
+        "                                 if <local> is already forwarded\n"
+        "  adb forward --remove <local> - remove a specific forward socket connection\n"
+        "  adb forward --remove-all     - remove all forward socket connections\n"
+        "  adb reverse --list           - list all reverse socket connections from device\n"
+        "  adb reverse <remote> <local> - reverse socket connections\n"
+        "                                 reverse specs are one of:\n"
+        "                                   tcp:<port>\n"
+        "                                   localabstract:<unix domain socket name>\n"
+        "                                   localreserved:<unix domain socket name>\n"
+        "                                   localfilesystem:<unix domain socket name>\n"
+        "  adb reverse --norebind <remote> <local>\n"
+        "                               - same as 'adb reverse <remote> <local>' but fails\n"
+        "                                 if <remote> is already reversed.\n"
+        "  adb reverse --remove <remote>\n"
+        "                               - remove a specific reversed socket connection\n"
+        "  adb reverse --remove-all     - remove all reversed socket connections from device\n"
+        "  adb jdwp                     - list PIDs of processes hosting a JDWP transport\n"
+        "  adb install [-l] [-r] [-d] [-s] [--algo <algorithm name> --key <hex-encoded key> --iv <hex-encoded iv>] <file>\n"
+        "                               - push this package file to the device and install it\n"
+        "                                 ('-l' means forward-lock the app)\n"
+        "                                 ('-r' means reinstall the app, keeping its data)\n"
+        "                                 ('-d' means allow version code downgrade)\n"
+        "                                 ('-s' means install on SD card instead of internal storage)\n"
+        "                                 ('--algo', '--key', and '--iv' mean the file is encrypted already)\n"
+        "  adb uninstall [-k] <package> - remove this app package from the device\n"
+        "                                 ('-k' means keep the data and cache directories)\n"
+        "  adb bugreport                - return all information from the device\n"
+        "                                 that should be included in a bug report.\n"
+        "\n"
+        "  adb backup [-f <file>] [-apk|-noapk] [-obb|-noobb] [-shared|-noshared] [-all] [-system|-nosystem] [<packages...>]\n"
+        "                               - write an archive of the device's data to <file>.\n"
+        "                                 If no -f option is supplied then the data is written\n"
+        "                                 to \"backup.ab\" in the current directory.\n"
+        "                                 (-apk|-noapk enable/disable backup of the .apks themselves\n"
+        "                                    in the archive; the default is noapk.)\n"
+        "                                 (-obb|-noobb enable/disable backup of any installed apk expansion\n"
+        "                                    (aka .obb) files associated with each application; the default\n"
+        "                                    is noobb.)\n"
+        "                                 (-shared|-noshared enable/disable backup of the device's\n"
+        "                                    shared storage / SD card contents; the default is noshared.)\n"
+        "                                 (-all means to back up all installed applications)\n"
+        "                                 (-system|-nosystem toggles whether -all automatically includes\n"
+        "                                    system applications; the default is to include system apps)\n"
+        "                                 (<packages...> is the list of applications to be backed up.  If\n"
+        "                                    the -all or -shared flags are passed, then the package\n"
+        "                                    list is optional.  Applications explicitly given on the\n"
+        "                                    command line will be included even if -nosystem would\n"
+        "                                    ordinarily cause them to be omitted.)\n"
+        "\n"
+        "  adb restore <file>           - restore device contents from the <file> backup archive\n"
+        "\n"
+        "  adb help                     - show this help message\n"
+        "  adb version                  - show version num\n"
+        "\n"
+        "scripting:\n"
+        "  adb wait-for-device          - block until device is online\n"
+        "  adb start-server             - ensure that there is a server running\n"
+        "  adb kill-server              - kill the server if it is running\n"
+        "  adb get-state                - prints: offline | bootloader | device\n"
+        "  adb get-serialno             - prints: <serial-number>\n"
+        "  adb get-devpath              - prints: <device-path>\n"
+        "  adb status-window            - continuously print device status for a specified device\n"
+        "  adb remount                  - remounts the /system partition on the device read-write\n"
+        "  adb reboot [bootloader|recovery] - reboots the device, optionally into the bootloader or recovery program\n"
+        "  adb reboot-bootloader        - reboots the device into the bootloader\n"
+        "  adb root                     - restarts the adbd daemon with root permissions\n"
+        "  adb usb                      - restarts the adbd daemon listening on USB\n"
+        "  adb tcpip <port>             - restarts the adbd daemon listening on TCP on the specified port"
+        "\n"
+        "networking:\n"
+        "  adb ppp <tty> [parameters]   - Run PPP over USB.\n"
+        " Note: you should not automatically start a PPP connection.\n"
+        " <tty> refers to the tty for PPP stream. Eg. dev:/dev/omap_csmi_tty1\n"
+        " [parameters] - Eg. defaultroute debug dump local notty usepeerdns\n"
+        "\n"
+        "adb sync notes: adb sync [ <directory> ]\n"
+        "  <localdir> can be interpreted in several ways:\n"
+        "\n"
+        "  - If <directory> is not specified, both /system and /data partitions will be updated.\n"
+        "\n"
+        "  - If it is \"system\" or \"data\", only the corresponding partition\n"
+        "    is updated.\n"
+        "\n"
+        "environmental variables:\n"
+        "  ADB_TRACE                    - Print debug information. A comma separated list of the following values\n"
+        "                                 1 or all, adb, sockets, packets, rwx, usb, sync, sysdeps, transport, jdwp\n"
+        "  ANDROID_SERIAL               - The serial number to connect to. -s takes priority over this if given.\n"
+        "  ANDROID_LOG_TAGS             - When used with the logcat option, only these debug tags are printed.\n"
+        );
+}
+
+int usage()
+{
+    help();
+    return 1;
+}
+
+#ifdef HAVE_TERMIO_H
+static struct termios tio_save;
+
+static void stdin_raw_init(int fd)
+{
+    struct termios tio;
+
+    if(tcgetattr(fd, &tio)) return;
+    if(tcgetattr(fd, &tio_save)) return;
+
+    tio.c_lflag = 0; /* disable CANON, ECHO*, etc */
+
+        /* no timeout but request at least one character per read */
+    tio.c_cc[VTIME] = 0;
+    tio.c_cc[VMIN] = 1;
+
+    tcsetattr(fd, TCSANOW, &tio);
+    tcflush(fd, TCIFLUSH);
+}
+
+static void stdin_raw_restore(int fd)
+{
+    tcsetattr(fd, TCSANOW, &tio_save);
+    tcflush(fd, TCIFLUSH);
+}
+#endif
+
+static void read_and_dump(int fd)
+{
+    char buf[4096];
+    int len;
+
+    while(fd >= 0) {
+        D("read_and_dump(): pre adb_read(fd=%d)\n", fd);
+        len = adb_read(fd, buf, 4096);
+        D("read_and_dump(): post adb_read(fd=%d): len=%d\n", fd, len);
+        if(len == 0) {
+            break;
+        }
+
+        if(len < 0) {
+            if(errno == EINTR) continue;
+            break;
+        }
+        fwrite(buf, 1, len, stdout);
+        fflush(stdout);
+    }
+}
+
+static void copy_to_file(int inFd, int outFd) {
+    const size_t BUFSIZE = 32 * 1024;
+    char* buf = (char*) malloc(BUFSIZE);
+    int len;
+    long total = 0;
+
+    D("copy_to_file(%d -> %d)\n", inFd, outFd);
+#ifdef HAVE_TERMIO_H
+    if (inFd == STDIN_FILENO) {
+        stdin_raw_init(STDIN_FILENO);
+    }
+#endif
+    for (;;) {
+        if (inFd == STDIN_FILENO) {
+            len = unix_read(inFd, buf, BUFSIZE);
+        } else {
+            len = adb_read(inFd, buf, BUFSIZE);
+        }
+        if (len == 0) {
+            D("copy_to_file() : read 0 bytes; exiting\n");
+            break;
+        }
+        if (len < 0) {
+            if (errno == EINTR) {
+                D("copy_to_file() : EINTR, retrying\n");
+                continue;
+            }
+            D("copy_to_file() : error %d\n", errno);
+            break;
+        }
+        if (outFd == STDOUT_FILENO) {
+            fwrite(buf, 1, len, stdout);
+            fflush(stdout);
+        } else {
+            adb_write(outFd, buf, len);
+        }
+        total += len;
+    }
+#ifdef HAVE_TERMIO_H
+    if (inFd == STDIN_FILENO) {
+        stdin_raw_restore(STDIN_FILENO);
+    }
+#endif
+    D("copy_to_file() finished after %lu bytes\n", total);
+    free(buf);
+}
+
+static void *stdin_read_thread(void *x)
+{
+    int fd, fdi;
+    unsigned char buf[1024];
+    int r, n;
+    int state = 0;
+
+    int *fds = (int*) x;
+    fd = fds[0];
+    fdi = fds[1];
+    free(fds);
+
+    for(;;) {
+        /* fdi is really the client's stdin, so use read, not adb_read here */
+        D("stdin_read_thread(): pre unix_read(fdi=%d,...)\n", fdi);
+        r = unix_read(fdi, buf, 1024);
+        D("stdin_read_thread(): post unix_read(fdi=%d,...)\n", fdi);
+        if(r == 0) break;
+        if(r < 0) {
+            if(errno == EINTR) continue;
+            break;
+        }
+        for(n = 0; n < r; n++){
+            switch(buf[n]) {
+            case '\n':
+                state = 1;
+                break;
+            case '\r':
+                state = 1;
+                break;
+            case '~':
+                if(state == 1) state++;
+                break;
+            case '.':
+                if(state == 2) {
+                    fprintf(stderr,"\n* disconnect *\n");
+#ifdef HAVE_TERMIO_H
+                    stdin_raw_restore(fdi);
+#endif
+                    exit(0);
+                }
+            default:
+                state = 0;
+            }
+        }
+        r = adb_write(fd, buf, r);
+        if(r <= 0) {
+            break;
+        }
+    }
+    return 0;
+}
+
+int interactive_shell(void)
+{
+    adb_thread_t thr;
+    int fdi, fd;
+    int *fds;
+
+    fd = adb_connect("shell:");
+    if(fd < 0) {
+        fprintf(stderr,"error: %s\n", adb_error());
+        return 1;
+    }
+    fdi = 0; //dup(0);
+
+    fds = malloc(sizeof(int) * 2);
+    fds[0] = fd;
+    fds[1] = fdi;
+
+#ifdef HAVE_TERMIO_H
+    stdin_raw_init(fdi);
+#endif
+    adb_thread_create(&thr, stdin_read_thread, fds);
+    read_and_dump(fd);
+#ifdef HAVE_TERMIO_H
+    stdin_raw_restore(fdi);
+#endif
+    return 0;
+}
+
+
+static void format_host_command(char* buffer, size_t  buflen, const char* command, transport_type ttype, const char* serial)
+{
+    if (serial) {
+        snprintf(buffer, buflen, "host-serial:%s:%s", serial, command);
+    } else {
+        const char* prefix = "host";
+        if (ttype == kTransportUsb)
+            prefix = "host-usb";
+        else if (ttype == kTransportLocal)
+            prefix = "host-local";
+
+        snprintf(buffer, buflen, "%s:%s", prefix, command);
+    }
+}
+
+int adb_download_buffer(const char *service, const char *fn, const void* data, int sz,
+                        unsigned progress)
+{
+    char buf[4096];
+    unsigned total;
+    int fd;
+    const unsigned char *ptr;
+
+    sprintf(buf,"%s:%d", service, sz);
+    fd = adb_connect(buf);
+    if(fd < 0) {
+        fprintf(stderr,"error: %s\n", adb_error());
+        return -1;
+    }
+
+    int opt = CHUNK_SIZE;
+    opt = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
+
+    total = sz;
+    ptr = data;
+
+    if(progress) {
+        char *x = strrchr(service, ':');
+        if(x) service = x + 1;
+    }
+
+    while(sz > 0) {
+        unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz;
+        if(writex(fd, ptr, xfer)) {
+            adb_status(fd);
+            fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
+            return -1;
+        }
+        sz -= xfer;
+        ptr += xfer;
+        if(progress) {
+            printf("sending: '%s' %4d%%    \r", fn, (int)(100LL - ((100LL * sz) / (total))));
+            fflush(stdout);
+        }
+    }
+    if(progress) {
+        printf("\n");
+    }
+
+    if(readx(fd, buf, 4)){
+        fprintf(stderr,"* error reading response *\n");
+        adb_close(fd);
+        return -1;
+    }
+    if(memcmp(buf, "OKAY", 4)) {
+        buf[4] = 0;
+        fprintf(stderr,"* error response '%s' *\n", buf);
+        adb_close(fd);
+        return -1;
+    }
+
+    adb_close(fd);
+    return 0;
+}
+
+
+int adb_download(const char *service, const char *fn, unsigned progress)
+{
+    void *data;
+    unsigned sz;
+
+    data = load_file(fn, &sz);
+    if(data == 0) {
+        fprintf(stderr,"* cannot read '%s' *\n", fn);
+        return -1;
+    }
+
+    int status = adb_download_buffer(service, fn, data, sz, progress);
+    free(data);
+    return status;
+}
+
+static void status_window(transport_type ttype, const char* serial)
+{
+    char command[4096];
+    char *state = 0;
+    char *laststate = 0;
+
+        /* silence stderr */
+#ifdef _WIN32
+    /* XXX: TODO */
+#else
+    int  fd;
+    fd = unix_open("/dev/null", O_WRONLY);
+    dup2(fd, 2);
+    adb_close(fd);
+#endif
+
+    format_host_command(command, sizeof command, "get-state", ttype, serial);
+
+    for(;;) {
+        adb_sleep_ms(250);
+
+        if(state) {
+            free(state);
+            state = 0;
+        }
+
+        state = adb_query(command);
+
+        if(state) {
+            if(laststate && !strcmp(state,laststate)){
+                continue;
+            } else {
+                if(laststate) free(laststate);
+                laststate = strdup(state);
+            }
+        }
+
+        printf("%c[2J%c[2H", 27, 27);
+        printf("Android Debug Bridge\n");
+        printf("State: %s\n", state ? state : "offline");
+        fflush(stdout);
+    }
+}
+
+/** Duplicate and escape given argument. */
+static char *escape_arg(const char *s)
+{
+    const char *ts;
+    size_t alloc_len;
+    char *ret;
+    char *dest;
+
+    alloc_len = 0;
+    for (ts = s; *ts != '\0'; ts++) {
+        alloc_len++;
+        if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
+            alloc_len++;
+        }
+    }
+
+    if (alloc_len == 0) {
+        // Preserve empty arguments
+        ret = (char *) malloc(3);
+        ret[0] = '\"';
+        ret[1] = '\"';
+        ret[2] = '\0';
+        return ret;
+    }
+
+    ret = (char *) malloc(alloc_len + 1);
+    dest = ret;
+
+    for (ts = s; *ts != '\0'; ts++) {
+        if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
+            *dest++ = '\\';
+        }
+        *dest++ = *ts;
+    }
+    *dest++ = '\0';
+
+    return ret;
+}
+
+/**
+ * Run ppp in "notty" mode against a resource listed as the first parameter
+ * eg:
+ *
+ * ppp dev:/dev/omap_csmi_tty0 <ppp options>
+ *
+ */
+int ppp(int argc, char **argv)
+{
+#ifdef HAVE_WIN32_PROC
+    fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
+    return -1;
+#else
+    char *adb_service_name;
+    pid_t pid;
+    int fd;
+
+    if (argc < 2) {
+        fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
+                argv[0]);
+
+        return 1;
+    }
+
+    adb_service_name = argv[1];
+
+    fd = adb_connect(adb_service_name);
+
+    if(fd < 0) {
+        fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
+                adb_service_name, adb_error());
+        return 1;
+    }
+
+    pid = fork();
+
+    if (pid < 0) {
+        perror("from fork()");
+        return 1;
+    } else if (pid == 0) {
+        int err;
+        int i;
+        const char **ppp_args;
+
+        // copy args
+        ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
+        ppp_args[0] = "pppd";
+        for (i = 2 ; i < argc ; i++) {
+            //argv[2] and beyond become ppp_args[1] and beyond
+            ppp_args[i - 1] = argv[i];
+        }
+        ppp_args[i-1] = NULL;
+
+        // child side
+
+        dup2(fd, STDIN_FILENO);
+        dup2(fd, STDOUT_FILENO);
+        adb_close(STDERR_FILENO);
+        adb_close(fd);
+
+        err = execvp("pppd", (char * const *)ppp_args);
+
+        if (err < 0) {
+            perror("execing pppd");
+        }
+        exit(-1);
+    } else {
+        // parent side
+
+        adb_close(fd);
+        return 0;
+    }
+#endif /* !HAVE_WIN32_PROC */
+}
+
+static int send_shellcommand(transport_type transport, char* serial, char* buf)
+{
+    int fd, ret;
+
+    for(;;) {
+        fd = adb_connect(buf);
+        if(fd >= 0)
+            break;
+        fprintf(stderr,"- waiting for device -\n");
+        adb_sleep_ms(1000);
+        do_cmd(transport, serial, "wait-for-device", 0);
+    }
+
+    read_and_dump(fd);
+    ret = adb_close(fd);
+    if (ret)
+        perror("close");
+
+    return ret;
+}
+
+static int logcat(transport_type transport, char* serial, int argc, char **argv)
+{
+    char buf[4096];
+
+    char *log_tags;
+    char *quoted;
+
+    log_tags = getenv("ANDROID_LOG_TAGS");
+    quoted = escape_arg(log_tags == NULL ? "" : log_tags);
+    snprintf(buf, sizeof(buf),
+            "shell:export ANDROID_LOG_TAGS=\"%s\"; exec logcat", quoted);
+    free(quoted);
+
+    if (!strcmp(argv[0], "longcat")) {
+        strncat(buf, " -v long", sizeof(buf) - 1);
+    }
+
+    argc -= 1;
+    argv += 1;
+    while(argc-- > 0) {
+        quoted = escape_arg(*argv++);
+        strncat(buf, " ", sizeof(buf) - 1);
+        strncat(buf, quoted, sizeof(buf) - 1);
+        free(quoted);
+    }
+
+    send_shellcommand(transport, serial, buf);
+    return 0;
+}
+
+static int mkdirs(const char *path)
+{
+    int ret;
+    char *x = (char *)path + 1;
+
+    for(;;) {
+        x = adb_dirstart(x);
+        if(x == 0) return 0;
+        *x = 0;
+        ret = adb_mkdir(path, 0775);
+        *x = OS_PATH_SEPARATOR;
+        if((ret < 0) && (errno != EEXIST)) {
+            return ret;
+        }
+        x++;
+    }
+    return 0;
+}
+
+static int backup(int argc, char** argv) {
+    char buf[4096];
+    char default_name[32];
+    const char* filename = strcpy(default_name, "./backup.ab");
+    int fd, outFd;
+    int i, j;
+
+    /* find, extract, and use any -f argument */
+    for (i = 1; i < argc; i++) {
+        if (!strcmp("-f", argv[i])) {
+            if (i == argc-1) {
+                fprintf(stderr, "adb: -f passed with no filename\n");
+                return usage();
+            }
+            filename = argv[i+1];
+            for (j = i+2; j <= argc; ) {
+                argv[i++] = argv[j++];
+            }
+            argc -= 2;
+            argv[argc] = NULL;
+        }
+    }
+
+    /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
+    if (argc < 2) return usage();
+
+    adb_unlink(filename);
+    mkdirs(filename);
+    outFd = adb_creat(filename, 0640);
+    if (outFd < 0) {
+        fprintf(stderr, "adb: unable to open file %s\n", filename);
+        return -1;
+    }
+
+    snprintf(buf, sizeof(buf), "backup");
+    for (argc--, argv++; argc; argc--, argv++) {
+        strncat(buf, ":", sizeof(buf) - strlen(buf) - 1);
+        strncat(buf, argv[0], sizeof(buf) - strlen(buf) - 1);
+    }
+
+    D("backup. filename=%s buf=%s\n", filename, buf);
+    fd = adb_connect(buf);
+    if (fd < 0) {
+        fprintf(stderr, "adb: unable to connect for backup\n");
+        adb_close(outFd);
+        return -1;
+    }
+
+    printf("Now unlock your device and confirm the backup operation.\n");
+    copy_to_file(fd, outFd);
+
+    adb_close(fd);
+    adb_close(outFd);
+    return 0;
+}
+
+static int restore(int argc, char** argv) {
+    const char* filename;
+    int fd, tarFd;
+
+    if (argc != 2) return usage();
+
+    filename = argv[1];
+    tarFd = adb_open(filename, O_RDONLY);
+    if (tarFd < 0) {
+        fprintf(stderr, "adb: unable to open file %s\n", filename);
+        return -1;
+    }
+
+    fd = adb_connect("restore:");
+    if (fd < 0) {
+        fprintf(stderr, "adb: unable to connect for restore\n");
+        adb_close(tarFd);
+        return -1;
+    }
+
+    printf("Now unlock your device and confirm the restore operation.\n");
+    copy_to_file(tarFd, fd);
+
+    adb_close(fd);
+    adb_close(tarFd);
+    return 0;
+}
+
+#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
+static int top_works(const char *top)
+{
+    if (top != NULL && adb_is_absolute_host_path(top)) {
+        char path_buf[PATH_MAX];
+        snprintf(path_buf, sizeof(path_buf),
+                "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top);
+        return access(path_buf, F_OK) == 0;
+    }
+    return 0;
+}
+
+static char *find_top_from(const char *indir, char path_buf[PATH_MAX])
+{
+    strcpy(path_buf, indir);
+    while (1) {
+        if (top_works(path_buf)) {
+            return path_buf;
+        }
+        char *s = adb_dirstop(path_buf);
+        if (s != NULL) {
+            *s = '\0';
+        } else {
+            path_buf[0] = '\0';
+            return NULL;
+        }
+    }
+}
+
+static char *find_top(char path_buf[PATH_MAX])
+{
+    char *top = getenv("ANDROID_BUILD_TOP");
+    if (top != NULL && top[0] != '\0') {
+        if (!top_works(top)) {
+            fprintf(stderr, "adb: bad ANDROID_BUILD_TOP value \"%s\"\n", top);
+            return NULL;
+        }
+    } else {
+        top = getenv("TOP");
+        if (top != NULL && top[0] != '\0') {
+            if (!top_works(top)) {
+                fprintf(stderr, "adb: bad TOP value \"%s\"\n", top);
+                return NULL;
+            }
+        } else {
+            top = NULL;
+        }
+    }
+
+    if (top != NULL) {
+        /* The environment pointed to a top directory that works.
+         */
+        strcpy(path_buf, top);
+        return path_buf;
+    }
+
+    /* The environment didn't help.  Walk up the tree from the CWD
+     * to see if we can find the top.
+     */
+    char dir[PATH_MAX];
+    top = find_top_from(getcwd(dir, sizeof(dir)), path_buf);
+    if (top == NULL) {
+        /* If the CWD isn't under a good-looking top, see if the
+         * executable is.
+         */
+        get_my_path(dir, PATH_MAX);
+        top = find_top_from(dir, path_buf);
+    }
+    return top;
+}
+
+/* <hint> may be:
+ * - A simple product name
+ *   e.g., "sooner"
+TODO: debug?  sooner-debug, sooner:debug?
+ * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
+ *   e.g., "out/target/product/sooner"
+ * - An absolute path to the PRODUCT_OUT dir
+ *   e.g., "/src/device/out/target/product/sooner"
+ *
+ * Given <hint>, try to construct an absolute path to the
+ * ANDROID_PRODUCT_OUT dir.
+ */
+static const char *find_product_out_path(const char *hint)
+{
+    static char path_buf[PATH_MAX];
+
+    if (hint == NULL || hint[0] == '\0') {
+        return NULL;
+    }
+
+    /* If it's already absolute, don't bother doing any work.
+     */
+    if (adb_is_absolute_host_path(hint)) {
+        strcpy(path_buf, hint);
+        return path_buf;
+    }
+
+    /* If there are any slashes in it, assume it's a relative path;
+     * make it absolute.
+     */
+    if (adb_dirstart(hint) != NULL) {
+        if (getcwd(path_buf, sizeof(path_buf)) == NULL) {
+            fprintf(stderr, "adb: Couldn't get CWD: %s\n", strerror(errno));
+            return NULL;
+        }
+        if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) {
+            fprintf(stderr, "adb: Couldn't assemble path\n");
+            return NULL;
+        }
+        strcat(path_buf, OS_PATH_SEPARATOR_STR);
+        strcat(path_buf, hint);
+        return path_buf;
+    }
+
+    /* It's a string without any slashes.  Try to do something with it.
+     *
+     * Try to find the root of the build tree, and build a PRODUCT_OUT
+     * path from there.
+     */
+    char top_buf[PATH_MAX];
+    const char *top = find_top(top_buf);
+    if (top == NULL) {
+        fprintf(stderr, "adb: Couldn't find top of build tree\n");
+        return NULL;
+    }
+//TODO: if we have a way to indicate debug, look in out/debug/target/...
+    snprintf(path_buf, sizeof(path_buf),
+            "%s" OS_PATH_SEPARATOR_STR
+            "out" OS_PATH_SEPARATOR_STR
+            "target" OS_PATH_SEPARATOR_STR
+            "product" OS_PATH_SEPARATOR_STR
+            "%s", top_buf, hint);
+    if (access(path_buf, F_OK) < 0) {
+        fprintf(stderr, "adb: Couldn't find a product dir "
+                "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf);
+        return NULL;
+    }
+    return path_buf;
+}
+
+static void parse_push_pull_args(char **arg, int narg, char const **path1, char const **path2,
+                                 int *show_progress, int *copy_attrs) {
+    *show_progress = 0;
+    *copy_attrs = 0;
+
+    while (narg > 0) {
+        if (!strcmp(*arg, "-p")) {
+            *show_progress = 1;
+        } else if (!strcmp(*arg, "-a")) {
+            *copy_attrs = 1;
+        } else {
+            break;
+        }
+        ++arg;
+        --narg;
+    }
+
+    if (narg > 0) {
+        *path1 = *arg;
+        ++arg;
+        --narg;
+    }
+
+    if (narg > 0) {
+        *path2 = *arg;
+    }
+}
+
+int adb_commandline(int argc, char **argv)
+{
+    char buf[4096];
+    int no_daemon = 0;
+    int is_daemon = 0;
+    int is_server = 0;
+    int persist = 0;
+    int r;
+    transport_type ttype = kTransportAny;
+    char* serial = NULL;
+    char* server_port_str = NULL;
+
+        /* If defined, this should be an absolute path to
+         * the directory containing all of the various system images
+         * for a particular product.  If not defined, and the adb
+         * command requires this information, then the user must
+         * specify the path using "-p".
+         */
+    gProductOutPath = getenv("ANDROID_PRODUCT_OUT");
+    if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
+        gProductOutPath = NULL;
+    }
+    // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
+
+    serial = getenv("ANDROID_SERIAL");
+
+    /* Validate and assign the server port */
+    server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
+    int server_port = DEFAULT_ADB_PORT;
+    if (server_port_str && strlen(server_port_str) > 0) {
+        server_port = (int) strtol(server_port_str, NULL, 0);
+        if (server_port <= 0 || server_port > 65535) {
+            fprintf(stderr,
+                    "adb: Env var ANDROID_ADB_SERVER_PORT must be a positive number less than 65535. Got \"%s\"\n",
+                    server_port_str);
+            return usage();
+        }
+    }
+
+    /* modifiers and flags */
+    while(argc > 0) {
+        if(!strcmp(argv[0],"server")) {
+            is_server = 1;
+        } else if(!strcmp(argv[0],"nodaemon")) {
+            no_daemon = 1;
+        } else if (!strcmp(argv[0], "fork-server")) {
+            /* this is a special flag used only when the ADB client launches the ADB Server */
+            is_daemon = 1;
+        } else if(!strcmp(argv[0],"persist")) {
+            persist = 1;
+        } else if(!strncmp(argv[0], "-p", 2)) {
+            const char *product = NULL;
+            if (argv[0][2] == '\0') {
+                if (argc < 2) return usage();
+                product = argv[1];
+                argc--;
+                argv++;
+            } else {
+                product = argv[0] + 2;
+            }
+            gProductOutPath = find_product_out_path(product);
+            if (gProductOutPath == NULL) {
+                fprintf(stderr, "adb: could not resolve \"-p %s\"\n",
+                        product);
+                return usage();
+            }
+        } else if (argv[0][0]=='-' && argv[0][1]=='s') {
+            if (isdigit(argv[0][2])) {
+                serial = argv[0] + 2;
+            } else {
+                if(argc < 2 || argv[0][2] != '\0') return usage();
+                serial = argv[1];
+                argc--;
+                argv++;
+            }
+        } else if (!strcmp(argv[0],"-d")) {
+            ttype = kTransportUsb;
+        } else if (!strcmp(argv[0],"-e")) {
+            ttype = kTransportLocal;
+        } else if (!strcmp(argv[0],"-a")) {
+            gListenAll = 1;
+        } else if(!strncmp(argv[0], "-H", 2)) {
+            const char *hostname = NULL;
+            if (argv[0][2] == '\0') {
+                if (argc < 2) return usage();
+                hostname = argv[1];
+                argc--;
+                argv++;
+            } else {
+                hostname = argv[0] + 2;
+            }
+            adb_set_tcp_name(hostname);
+
+        } else if(!strncmp(argv[0], "-P", 2)) {
+            if (argv[0][2] == '\0') {
+                if (argc < 2) return usage();
+                server_port_str = argv[1];
+                argc--;
+                argv++;
+            } else {
+                server_port_str = argv[0] + 2;
+            }
+            if (strlen(server_port_str) > 0) {
+                server_port = (int) strtol(server_port_str, NULL, 0);
+                if (server_port <= 0 || server_port > 65535) {
+                    fprintf(stderr,
+                            "adb: port number must be a positive number less than 65536. Got \"%s\"\n",
+                            server_port_str);
+                    return usage();
+                }
+            } else {
+                fprintf(stderr,
+                "adb: port number must be a positive number less than 65536. Got empty string.\n");
+                return usage();
+            }
+        } else {
+                /* out of recognized modifiers and flags */
+            break;
+        }
+        argc--;
+        argv++;
+    }
+
+    adb_set_transport(ttype, serial);
+    adb_set_tcp_specifics(server_port);
+
+    if (is_server) {
+        if (no_daemon || is_daemon) {
+            r = adb_main(is_daemon, server_port);
+        } else {
+            r = launch_server(server_port);
+        }
+        if(r) {
+            fprintf(stderr,"* could not start server *\n");
+        }
+        return r;
+    }
+
+top:
+    if(argc == 0) {
+        return usage();
+    }
+
+    /* adb_connect() commands */
+
+    if(!strcmp(argv[0], "devices")) {
+        char *tmp;
+        char *listopt;
+        if (argc < 2)
+            listopt = "";
+        else if (argc == 2 && !strcmp(argv[1], "-l"))
+            listopt = argv[1];
+        else {
+            fprintf(stderr, "Usage: adb devices [-l]\n");
+            return 1;
+        }
+        snprintf(buf, sizeof buf, "host:%s%s", argv[0], listopt);
+        tmp = adb_query(buf);
+        if(tmp) {
+            printf("List of devices attached \n");
+            printf("%s\n", tmp);
+            return 0;
+        } else {
+            return 1;
+        }
+    }
+
+    if(!strcmp(argv[0], "connect")) {
+        char *tmp;
+        if (argc != 2) {
+            fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
+            return 1;
+        }
+        snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
+        tmp = adb_query(buf);
+        if(tmp) {
+            printf("%s\n", tmp);
+            return 0;
+        } else {
+            return 1;
+        }
+    }
+
+    if(!strcmp(argv[0], "disconnect")) {
+        char *tmp;
+        if (argc > 2) {
+            fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
+            return 1;
+        }
+        if (argc == 2) {
+            snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
+        } else {
+            snprintf(buf, sizeof buf, "host:disconnect:");
+        }
+        tmp = adb_query(buf);
+        if(tmp) {
+            printf("%s\n", tmp);
+            return 0;
+        } else {
+            return 1;
+        }
+    }
+
+    if (!strcmp(argv[0], "emu")) {
+        return adb_send_emulator_command(argc, argv);
+    }
+
+    if(!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
+        int r;
+        int fd;
+
+        char h = (argv[0][0] == 'h');
+
+        if (h) {
+            printf("\x1b[41;33m");
+            fflush(stdout);
+        }
+
+        if(argc < 2) {
+            D("starting interactive shell\n");
+            r = interactive_shell();
+            if (h) {
+                printf("\x1b[0m");
+                fflush(stdout);
+            }
+            return r;
+        }
+
+        snprintf(buf, sizeof(buf), "shell:%s", argv[1]);
+        argc -= 2;
+        argv += 2;
+        while (argc-- > 0) {
+            char *quoted = escape_arg(*argv++);
+            strncat(buf, " ", sizeof(buf) - 1);
+            strncat(buf, quoted, sizeof(buf) - 1);
+            free(quoted);
+        }
+
+        for(;;) {
+            D("interactive shell loop. buff=%s\n", buf);
+            fd = adb_connect(buf);
+            if(fd >= 0) {
+                D("about to read_and_dump(fd=%d)\n", fd);
+                read_and_dump(fd);
+                D("read_and_dump() done.\n");
+                adb_close(fd);
+                r = 0;
+            } else {
+                fprintf(stderr,"error: %s\n", adb_error());
+                r = -1;
+            }
+
+            if(persist) {
+                fprintf(stderr,"\n- waiting for device -\n");
+                adb_sleep_ms(1000);
+                do_cmd(ttype, serial, "wait-for-device", 0);
+            } else {
+                if (h) {
+                    printf("\x1b[0m");
+                    fflush(stdout);
+                }
+                D("interactive shell loop. return r=%d\n", r);
+                return r;
+            }
+        }
+    }
+
+    if (!strcmp(argv[0], "exec-in") || !strcmp(argv[0], "exec-out")) {
+        int exec_in = !strcmp(argv[0], "exec-in");
+        int fd;
+
+        snprintf(buf, sizeof buf, "exec:%s", argv[1]);
+        argc -= 2;
+        argv += 2;
+        while (argc-- > 0) {
+            char *quoted = escape_arg(*argv++);
+            strncat(buf, " ", sizeof(buf) - 1);
+            strncat(buf, quoted, sizeof(buf) - 1);
+            free(quoted);
+        }
+
+        fd = adb_connect(buf);
+        if (fd < 0) {
+            fprintf(stderr, "error: %s\n", adb_error());
+            return -1;
+        }
+
+        if (exec_in) {
+            copy_to_file(STDIN_FILENO, fd);
+        } else {
+            copy_to_file(fd, STDOUT_FILENO);
+        }
+
+        adb_close(fd);
+        return 0;
+    }
+
+    if(!strcmp(argv[0], "kill-server")) {
+        int fd;
+        fd = _adb_connect("host:kill");
+        if(fd == -1) {
+            fprintf(stderr,"* server not running *\n");
+            return 1;
+        }
+        return 0;
+    }
+
+    if(!strcmp(argv[0], "sideload")) {
+        if(argc != 2) return usage();
+        if(adb_download("sideload", argv[1], 1)) {
+            return 1;
+        } else {
+            return 0;
+        }
+    }
+
+    if(!strcmp(argv[0], "remount") || !strcmp(argv[0], "reboot")
+            || !strcmp(argv[0], "reboot-bootloader")
+            || !strcmp(argv[0], "tcpip") || !strcmp(argv[0], "usb")
+            || !strcmp(argv[0], "root")) {
+        char command[100];
+        if (!strcmp(argv[0], "reboot-bootloader"))
+            snprintf(command, sizeof(command), "reboot:bootloader");
+        else if (argc > 1)
+            snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
+        else
+            snprintf(command, sizeof(command), "%s:", argv[0]);
+        int fd = adb_connect(command);
+        if(fd >= 0) {
+            read_and_dump(fd);
+            adb_close(fd);
+            return 0;
+        }
+        fprintf(stderr,"error: %s\n", adb_error());
+        return 1;
+    }
+
+    if(!strcmp(argv[0], "bugreport")) {
+        if (argc != 1) return usage();
+        do_cmd(ttype, serial, "shell", "bugreport", 0);
+        return 0;
+    }
+
+    /* adb_command() wrapper commands */
+
+    if(!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
+        char* service = argv[0];
+        if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
+            if (ttype == kTransportUsb) {
+                service = "wait-for-usb";
+            } else if (ttype == kTransportLocal) {
+                service = "wait-for-local";
+            } else {
+                service = "wait-for-any";
+            }
+        }
+
+        format_host_command(buf, sizeof buf, service, ttype, serial);
+
+        if (adb_command(buf)) {
+            D("failure: %s *\n",adb_error());
+            fprintf(stderr,"error: %s\n", adb_error());
+            return 1;
+        }
+
+        /* Allow a command to be run after wait-for-device,
+            * e.g. 'adb wait-for-device shell'.
+            */
+        if(argc > 1) {
+            argc--;
+            argv++;
+            goto top;
+        }
+        return 0;
+    }
+
+    if(!strcmp(argv[0], "forward") ||
+       !strcmp(argv[0], "reverse"))
+    {
+        char host_prefix[64];
+        char reverse = (char) !strcmp(argv[0], "reverse");
+        char remove = 0;
+        char remove_all = 0;
+        char list = 0;
+        char no_rebind = 0;
+
+        // Parse options here.
+        while (argc > 1 && argv[1][0] == '-') {
+            if (!strcmp(argv[1], "--list"))
+                list = 1;
+            else if (!strcmp(argv[1], "--remove"))
+                remove = 1;
+            else if (!strcmp(argv[1], "--remove-all"))
+                remove_all = 1;
+            else if (!strcmp(argv[1], "--no-rebind"))
+                no_rebind = 1;
+            else {
+                return usage();
+            }
+            argc--;
+            argv++;
+        }
+
+        // Ensure we can only use one option at a time.
+        if (list + remove + remove_all + no_rebind > 1) {
+            return usage();
+        }
+
+        // Determine the <host-prefix> for this command.
+        if (reverse) {
+            snprintf(host_prefix, sizeof host_prefix, "reverse");
+        } else {
+            if (serial) {
+                snprintf(host_prefix, sizeof host_prefix, "host-serial:%s",
+                        serial);
+            } else if (ttype == kTransportUsb) {
+                snprintf(host_prefix, sizeof host_prefix, "host-usb");
+            } else if (ttype == kTransportLocal) {
+                snprintf(host_prefix, sizeof host_prefix, "host-local");
+            } else {
+                snprintf(host_prefix, sizeof host_prefix, "host");
+            }
+        }
+
+        // Implement forward --list
+        if (list) {
+            if (argc != 1)
+                return usage();
+            snprintf(buf, sizeof buf, "%s:list-forward", host_prefix);
+            char* forwards = adb_query(buf);
+            if (forwards == NULL) {
+                fprintf(stderr, "error: %s\n", adb_error());
+                return 1;
+            }
+            printf("%s", forwards);
+            free(forwards);
+            return 0;
+        }
+
+        // Implement forward --remove-all
+        else if (remove_all) {
+            if (argc != 1)
+                return usage();
+            snprintf(buf, sizeof buf, "%s:killforward-all", host_prefix);
+        }
+
+        // Implement forward --remove <local>
+        else if (remove) {
+            if (argc != 2)
+                return usage();
+            snprintf(buf, sizeof buf, "%s:killforward:%s", host_prefix, argv[1]);
+        }
+        // Or implement one of:
+        //    forward <local> <remote>
+        //    forward --no-rebind <local> <remote>
+        else
+        {
+          if (argc != 3)
+            return usage();
+          const char* command = no_rebind ? "forward:norebind:" : "forward";
+          snprintf(buf, sizeof buf, "%s:%s:%s;%s", host_prefix, command, argv[1], argv[2]);
+        }
+
+        if(adb_command(buf)) {
+            fprintf(stderr,"error: %s\n", adb_error());
+            return 1;
+        }
+        return 0;
+    }
+
+    /* do_sync_*() commands */
+
+    if(!strcmp(argv[0], "ls")) {
+        if(argc != 2) return usage();
+        return do_sync_ls(argv[1]);
+    }
+
+    if(!strcmp(argv[0], "push")) {
+        int show_progress = 0;
+        int copy_attrs = 0; // unused
+        const char* lpath = NULL, *rpath = NULL;
+
+        parse_push_pull_args(&argv[1], argc - 1, &lpath, &rpath, &show_progress, &copy_attrs);
+
+        if ((lpath != NULL) && (rpath != NULL)) {
+            return do_sync_push(lpath, rpath, 0 /* no verify APK */, show_progress);
+        }
+
+        return usage();
+    }
+
+    if(!strcmp(argv[0], "pull")) {
+        int show_progress = 0;
+        int copy_attrs = 0;
+        const char* rpath = NULL, *lpath = ".";
+
+        parse_push_pull_args(&argv[1], argc - 1, &rpath, &lpath, &show_progress, &copy_attrs);
+
+        if (rpath != NULL) {
+            return do_sync_pull(rpath, lpath, show_progress, copy_attrs);
+        }
+
+        return usage();
+    }
+
+    if(!strcmp(argv[0], "install")) {
+        if (argc < 2) return usage();
+        return install_app(ttype, serial, argc, argv);
+    }
+
+    if(!strcmp(argv[0], "uninstall")) {
+        if (argc < 2) return usage();
+        return uninstall_app(ttype, serial, argc, argv);
+    }
+
+    if(!strcmp(argv[0], "sync")) {
+        char *srcarg, *android_srcpath, *data_srcpath;
+        int listonly = 0;
+
+        int ret;
+        if(argc < 2) {
+            /* No local path was specified. */
+            srcarg = NULL;
+        } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
+            listonly = 1;
+            if (argc == 3) {
+                srcarg = argv[2];
+            } else {
+                srcarg = NULL;
+            }
+        } else if(argc == 2) {
+            /* A local path or "android"/"data" arg was specified. */
+            srcarg = argv[1];
+        } else {
+            return usage();
+        }
+        ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath);
+        if(ret != 0) return usage();
+
+        if(android_srcpath != NULL)
+            ret = do_sync_sync(android_srcpath, "/system", listonly);
+        if(ret == 0 && data_srcpath != NULL)
+            ret = do_sync_sync(data_srcpath, "/data", listonly);
+
+        free(android_srcpath);
+        free(data_srcpath);
+        return ret;
+    }
+
+    /* passthrough commands */
+
+    if(!strcmp(argv[0],"get-state") ||
+        !strcmp(argv[0],"get-serialno") ||
+        !strcmp(argv[0],"get-devpath"))
+    {
+        char *tmp;
+
+        format_host_command(buf, sizeof buf, argv[0], ttype, serial);
+        tmp = adb_query(buf);
+        if(tmp) {
+            printf("%s\n", tmp);
+            return 0;
+        } else {
+            return 1;
+        }
+    }
+
+    /* other commands */
+
+    if(!strcmp(argv[0],"status-window")) {
+        status_window(ttype, serial);
+        return 0;
+    }
+
+    if(!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
+        return logcat(ttype, serial, argc, argv);
+    }
+
+    if(!strcmp(argv[0],"ppp")) {
+        return ppp(argc, argv);
+    }
+
+    if (!strcmp(argv[0], "start-server")) {
+        return adb_connect("host:start-server");
+    }
+
+    if (!strcmp(argv[0], "backup")) {
+        return backup(argc, argv);
+    }
+
+    if (!strcmp(argv[0], "restore")) {
+        return restore(argc, argv);
+    }
+
+    if (!strcmp(argv[0], "jdwp")) {
+        int  fd = adb_connect("jdwp");
+        if (fd >= 0) {
+            read_and_dump(fd);
+            adb_close(fd);
+            return 0;
+        } else {
+            fprintf(stderr, "error: %s\n", adb_error());
+            return -1;
+        }
+    }
+
+    /* "adb /?" is a common idiom under Windows */
+    if(!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
+        help();
+        return 0;
+    }
+
+    if(!strcmp(argv[0], "version")) {
+        version(stdout);
+        return 0;
+    }
+
+    usage();
+    return 1;
+}
+
+static int do_cmd(transport_type ttype, char* serial, char *cmd, ...)
+{
+    char *argv[16];
+    int argc;
+    va_list ap;
+
+    va_start(ap, cmd);
+    argc = 0;
+
+    if (serial) {
+        argv[argc++] = "-s";
+        argv[argc++] = serial;
+    } else if (ttype == kTransportUsb) {
+        argv[argc++] = "-d";
+    } else if (ttype == kTransportLocal) {
+        argv[argc++] = "-e";
+    }
+
+    argv[argc++] = cmd;
+    while((argv[argc] = va_arg(ap, char*)) != 0) argc++;
+    va_end(ap);
+
+#if 0
+    int n;
+    fprintf(stderr,"argc = %d\n",argc);
+    for(n = 0; n < argc; n++) {
+        fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
+    }
+#endif
+
+    return adb_commandline(argc, argv);
+}
+
+int find_sync_dirs(const char *srcarg,
+        char **android_srcdir_out, char **data_srcdir_out)
+{
+    char *android_srcdir, *data_srcdir;
+
+    if(srcarg == NULL) {
+        android_srcdir = product_file("system");
+        data_srcdir = product_file("data");
+    } else {
+        /* srcarg may be "data", "system" or NULL.
+         * if srcarg is NULL, then both data and system are synced
+         */
+        if(strcmp(srcarg, "system") == 0) {
+            android_srcdir = product_file("system");
+            data_srcdir = NULL;
+        } else if(strcmp(srcarg, "data") == 0) {
+            android_srcdir = NULL;
+            data_srcdir = product_file("data");
+        } else {
+            /* It's not "system" or "data".
+             */
+            return 1;
+        }
+    }
+
+    if(android_srcdir_out != NULL)
+        *android_srcdir_out = android_srcdir;
+    else
+        free(android_srcdir);
+
+    if(data_srcdir_out != NULL)
+        *data_srcdir_out = data_srcdir;
+    else
+        free(data_srcdir);
+
+    return 0;
+}
+
+static int pm_command(transport_type transport, char* serial,
+                      int argc, char** argv)
+{
+    char buf[4096];
+
+    snprintf(buf, sizeof(buf), "shell:pm");
+
+    while(argc-- > 0) {
+        char *quoted = escape_arg(*argv++);
+        strncat(buf, " ", sizeof(buf) - 1);
+        strncat(buf, quoted, sizeof(buf) - 1);
+        free(quoted);
+    }
+
+    send_shellcommand(transport, serial, buf);
+    return 0;
+}
+
+int uninstall_app(transport_type transport, char* serial, int argc, char** argv)
+{
+    /* if the user choose the -k option, we refuse to do it until devices are
+       out with the option to uninstall the remaining data somehow (adb/ui) */
+    if (argc == 3 && strcmp(argv[1], "-k") == 0)
+    {
+        printf(
+            "The -k option uninstalls the application while retaining the data/cache.\n"
+            "At the moment, there is no way to remove the remaining data.\n"
+            "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
+            "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
+        return -1;
+    }
+
+    /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
+    return pm_command(transport, serial, argc, argv);
+}
+
+static int delete_file(transport_type transport, char* serial, char* filename)
+{
+    char buf[4096];
+    char* quoted;
+
+    snprintf(buf, sizeof(buf), "shell:rm ");
+    quoted = escape_arg(filename);
+    strncat(buf, quoted, sizeof(buf)-1);
+    free(quoted);
+
+    send_shellcommand(transport, serial, buf);
+    return 0;
+}
+
+static const char* get_basename(const char* filename)
+{
+    const char* basename = adb_dirstop(filename);
+    if (basename) {
+        basename++;
+        return basename;
+    } else {
+        return filename;
+    }
+}
+
+static int check_file(const char* filename)
+{
+    struct stat st;
+
+    if (filename == NULL) {
+        return 0;
+    }
+
+    if (stat(filename, &st) != 0) {
+        fprintf(stderr, "can't find '%s' to install\n", filename);
+        return 1;
+    }
+
+    if (!S_ISREG(st.st_mode)) {
+        fprintf(stderr, "can't install '%s' because it's not a file\n", filename);
+        return 1;
+    }
+
+    return 0;
+}
+
+int install_app(transport_type transport, char* serial, int argc, char** argv)
+{
+    static const char *const DATA_DEST = "/data/local/tmp/%s";
+    static const char *const SD_DEST = "/sdcard/tmp/%s";
+    const char* where = DATA_DEST;
+    char apk_dest[PATH_MAX];
+    char verification_dest[PATH_MAX];
+    char* apk_file;
+    char* verification_file = NULL;
+    int file_arg = -1;
+    int err;
+    int i;
+    int verify_apk = 1;
+
+    for (i = 1; i < argc; i++) {
+        if (*argv[i] != '-') {
+            file_arg = i;
+            break;
+        } else if (!strcmp(argv[i], "-i")) {
+            // Skip the installer package name.
+            i++;
+        } else if (!strcmp(argv[i], "-s")) {
+            where = SD_DEST;
+        } else if (!strcmp(argv[i], "--algo")) {
+            verify_apk = 0;
+            i++;
+        } else if (!strcmp(argv[i], "--iv")) {
+            verify_apk = 0;
+            i++;
+        } else if (!strcmp(argv[i], "--key")) {
+            verify_apk = 0;
+            i++;
+        } else if (!strcmp(argv[i], "--abi")) {
+            i++;
+        }
+    }
+
+    if (file_arg < 0) {
+        fprintf(stderr, "can't find filename in arguments\n");
+        return 1;
+    } else if (file_arg + 2 < argc) {
+        fprintf(stderr, "too many files specified; only takes APK file and verifier file\n");
+        return 1;
+    }
+
+    apk_file = argv[file_arg];
+
+    if (file_arg != argc - 1) {
+        verification_file = argv[file_arg + 1];
+    }
+
+    if (check_file(apk_file) || check_file(verification_file)) {
+        return 1;
+    }
+
+    snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
+    if (verification_file != NULL) {
+        snprintf(verification_dest, sizeof(verification_dest), where, get_basename(verification_file));
+
+        if (!strcmp(apk_dest, verification_dest)) {
+            fprintf(stderr, "APK and verification file can't have the same name\n");
+            return 1;
+        }
+    }
+
+    err = do_sync_push(apk_file, apk_dest, verify_apk, 0 /* no show progress */);
+    if (err) {
+        goto cleanup_apk;
+    } else {
+        argv[file_arg] = apk_dest; /* destination name, not source location */
+    }
+
+    if (verification_file != NULL) {
+        err = do_sync_push(verification_file, verification_dest, 0 /* no verify APK */,
+                           0 /* no show progress */);
+        if (err) {
+            goto cleanup_apk;
+        } else {
+            argv[file_arg + 1] = verification_dest; /* destination name, not source location */
+        }
+    }
+
+    pm_command(transport, serial, argc, argv);
+
+cleanup_apk:
+    if (verification_file != NULL) {
+        delete_file(transport, serial, verification_dest);
+    }
+
+    delete_file(transport, serial, apk_dest);
+
+    return err;
+}
diff --git a/package/utils/adbd/src/adb/console.c b/package/utils/adbd/src/adb/console.c
new file mode 100644
index 0000000..b813d33
--- /dev/null
+++ b/package/utils/adbd/src/adb/console.c
@@ -0,0 +1,45 @@
+#include "sysdeps.h"
+#include "adb.h"
+#include "adb_client.h"
+#include <stdio.h>
+
+static int  connect_to_console(void)
+{
+    int  fd, port;
+
+    port = adb_get_emulator_console_port();
+    if (port < 0) {
+        if (port == -2)
+            fprintf(stderr, "error: more than one emulator detected. use -s option\n");
+        else
+            fprintf(stderr, "error: no emulator detected\n");
+        return -1;
+    }
+    fd = socket_loopback_client( port, SOCK_STREAM );
+    if (fd < 0) {
+        fprintf(stderr, "error: could not connect to TCP port %d\n", port);
+        return -1;
+    }
+    return  fd;
+}
+
+
+int  adb_send_emulator_command(int  argc, char**  argv)
+{
+    int   fd, nn;
+
+    fd = connect_to_console();
+    if (fd < 0)
+        return 1;
+
+#define  QUIT  "quit\n"
+
+    for (nn = 1; nn < argc; nn++) {
+        adb_write( fd, argv[nn], strlen(argv[nn]) );
+        adb_write( fd, (nn == argc-1) ? "\n" : " ", 1 );
+    }
+    adb_write( fd, QUIT, sizeof(QUIT)-1 );
+    adb_close(fd);
+
+    return 0;
+}
diff --git a/package/utils/adbd/src/adb/fdevent.c b/package/utils/adbd/src/adb/fdevent.c
new file mode 100644
index 0000000..5c374a7
--- /dev/null
+++ b/package/utils/adbd/src/adb/fdevent.c
@@ -0,0 +1,695 @@
+/* http://frotznet.googlecode.com/svn/trunk/utils/fdevent.c
+**
+** Copyright 2006, Brian Swetland <swetland@frotz.net>
+**
+** 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 <sys/ioctl.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <fcntl.h>
+
+#include <stdarg.h>
+#include <stddef.h>
+
+#include "fdevent.h"
+#include "transport.h"
+#include "sysdeps.h"
+
+
+/* !!! Do not enable DEBUG for the adb that will run as the server:
+** both stdout and stderr are used to communicate between the client
+** and server. Any extra output will cause failures.
+*/
+#define DEBUG 0   /* non-0 will break adb server */
+
+// This socket is used when a subproc shell service exists.
+// It wakes up the fdevent_loop() and cause the correct handling
+// of the shell's pseudo-tty master. I.e. force close it.
+int SHELL_EXIT_NOTIFY_FD = -1;
+
+static void fatal(const char *fn, const char *fmt, ...)
+{
+    va_list ap;
+    va_start(ap, fmt);
+    fprintf(stderr, "%s:", fn);
+    vfprintf(stderr, fmt, ap);
+    va_end(ap);
+    abort();
+}
+
+#define FATAL(x...) fatal(__FUNCTION__, x)
+
+#if DEBUG
+#define D(...) \
+    do { \
+        adb_mutex_lock(&D_lock);               \
+        int save_errno = errno;                \
+        fprintf(stderr, "%s::%s():", __FILE__, __FUNCTION__);  \
+        errno = save_errno;                    \
+        fprintf(stderr, __VA_ARGS__);          \
+        adb_mutex_unlock(&D_lock);             \
+        errno = save_errno;                    \
+    } while(0)
+static void dump_fde(fdevent *fde, const char *info)
+{
+    adb_mutex_lock(&D_lock);
+    fprintf(stderr,"FDE #%03d %c%c%c %s\n", fde->fd,
+            fde->state & FDE_READ ? 'R' : ' ',
+            fde->state & FDE_WRITE ? 'W' : ' ',
+            fde->state & FDE_ERROR ? 'E' : ' ',
+            info);
+    adb_mutex_unlock(&D_lock);
+}
+#else
+#define D(...) ((void)0)
+#define dump_fde(fde, info) do { } while(0)
+#endif
+
+#define FDE_EVENTMASK  0x00ff
+#define FDE_STATEMASK  0xff00
+
+#define FDE_ACTIVE     0x0100
+#define FDE_PENDING    0x0200
+#define FDE_CREATED    0x0400
+
+static void fdevent_plist_enqueue(fdevent *node);
+static void fdevent_plist_remove(fdevent *node);
+static fdevent *fdevent_plist_dequeue(void);
+static void fdevent_subproc_event_func(int fd, unsigned events, void *userdata);
+
+static fdevent list_pending = {
+    .next = &list_pending,
+    .prev = &list_pending,
+};
+
+static fdevent **fd_table = 0;
+static int fd_table_max = 0;
+
+#ifdef CRAPTASTIC
+//HAVE_EPOLL
+
+#include <sys/epoll.h>
+
+static int epoll_fd = -1;
+
+static void fdevent_init()
+{
+        /* XXX: what's a good size for the passed in hint? */
+    epoll_fd = epoll_create(256);
+
+    if(epoll_fd < 0) {
+        perror("epoll_create() failed");
+        exit(1);
+    }
+
+        /* mark for close-on-exec */
+    fcntl(epoll_fd, F_SETFD, FD_CLOEXEC);
+}
+
+static void fdevent_connect(fdevent *fde)
+{
+    struct epoll_event ev;
+
+    memset(&ev, 0, sizeof(ev));
+    ev.events = 0;
+    ev.data.ptr = fde;
+
+#if 0
+    if(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fde->fd, &ev)) {
+        perror("epoll_ctl() failed\n");
+        exit(1);
+    }
+#endif
+}
+
+static void fdevent_disconnect(fdevent *fde)
+{
+    struct epoll_event ev;
+
+    memset(&ev, 0, sizeof(ev));
+    ev.events = 0;
+    ev.data.ptr = fde;
+
+        /* technically we only need to delete if we
+        ** were actively monitoring events, but let's
+        ** be aggressive and do it anyway, just in case
+        ** something's out of sync
+        */
+    epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fde->fd, &ev);
+}
+
+static void fdevent_update(fdevent *fde, unsigned events)
+{
+    struct epoll_event ev;
+    int active;
+
+    active = (fde->state & FDE_EVENTMASK) != 0;
+
+    memset(&ev, 0, sizeof(ev));
+    ev.events = 0;
+    ev.data.ptr = fde;
+
+    if(events & FDE_READ) ev.events |= EPOLLIN;
+    if(events & FDE_WRITE) ev.events |= EPOLLOUT;
+    if(events & FDE_ERROR) ev.events |= (EPOLLERR | EPOLLHUP);
+
+    fde->state = (fde->state & FDE_STATEMASK) | events;
+
+    if(active) {
+            /* we're already active. if we're changing to *no*
+            ** events being monitored, we need to delete, otherwise
+            ** we need to just modify
+            */
+        if(ev.events) {
+            if(epoll_ctl(epoll_fd, EPOLL_CTL_MOD, fde->fd, &ev)) {
+                perror("epoll_ctl() failed\n");
+                exit(1);
+            }
+        } else {
+            if(epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fde->fd, &ev)) {
+                perror("epoll_ctl() failed\n");
+                exit(1);
+            }
+        }
+    } else {
+            /* we're not active.  if we're watching events, we need
+            ** to add, otherwise we can just do nothing
+            */
+        if(ev.events) {
+            if(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fde->fd, &ev)) {
+                perror("epoll_ctl() failed\n");
+                exit(1);
+            }
+        }
+    }
+}
+
+static void fdevent_process()
+{
+    struct epoll_event events[256];
+    fdevent *fde;
+    int i, n;
+
+    n = epoll_wait(epoll_fd, events, 256, -1);
+
+    if(n < 0) {
+        if(errno == EINTR) return;
+        perror("epoll_wait");
+        exit(1);
+    }
+
+    for(i = 0; i < n; i++) {
+        struct epoll_event *ev = events + i;
+        fde = ev->data.ptr;
+
+        if(ev->events & EPOLLIN) {
+            fde->events |= FDE_READ;
+        }
+        if(ev->events & EPOLLOUT) {
+            fde->events |= FDE_WRITE;
+        }
+        if(ev->events & (EPOLLERR | EPOLLHUP)) {
+            fde->events |= FDE_ERROR;
+        }
+        if(fde->events) {
+            if(fde->state & FDE_PENDING) continue;
+            fde->state |= FDE_PENDING;
+            fdevent_plist_enqueue(fde);
+        }
+    }
+}
+
+#else /* USE_SELECT */
+
+#ifdef HAVE_WINSOCK
+#include <winsock2.h>
+#else
+#include <sys/select.h>
+#endif
+
+static fd_set read_fds;
+static fd_set write_fds;
+static fd_set error_fds;
+
+static int select_n = 0;
+
+static void fdevent_init(void)
+{
+    FD_ZERO(&read_fds);
+    FD_ZERO(&write_fds);
+    FD_ZERO(&error_fds);
+}
+
+static void fdevent_connect(fdevent *fde)
+{
+    if(fde->fd >= select_n) {
+        select_n = fde->fd + 1;
+    }
+}
+
+static void fdevent_disconnect(fdevent *fde)
+{
+    int i, n;
+
+    FD_CLR(fde->fd, &read_fds);
+    FD_CLR(fde->fd, &write_fds);
+    FD_CLR(fde->fd, &error_fds);
+
+    for(n = 0, i = 0; i < select_n; i++) {
+        if(fd_table[i] != 0) n = i;
+    }
+    select_n = n + 1;
+}
+
+static void fdevent_update(fdevent *fde, unsigned events)
+{
+    if(events & FDE_READ) {
+        FD_SET(fde->fd, &read_fds);
+    } else {
+        FD_CLR(fde->fd, &read_fds);
+    }
+    if(events & FDE_WRITE) {
+        FD_SET(fde->fd, &write_fds);
+    } else {
+        FD_CLR(fde->fd, &write_fds);
+    }
+    if(events & FDE_ERROR) {
+        FD_SET(fde->fd, &error_fds);
+    } else {
+        FD_CLR(fde->fd, &error_fds);
+    }
+
+    fde->state = (fde->state & FDE_STATEMASK) | events;
+}
+
+/* Looks at fd_table[] for bad FDs and sets bit in fds.
+** Returns the number of bad FDs.
+*/
+static int fdevent_fd_check(fd_set *fds)
+{
+    int i, n = 0;
+    fdevent *fde;
+
+    for(i = 0; i < select_n; i++) {
+        fde = fd_table[i];
+        if(fde == 0) continue;
+        if(fcntl(i, F_GETFL, NULL) < 0) {
+            FD_SET(i, fds);
+            n++;
+            // fde->state |= FDE_DONT_CLOSE;
+
+        }
+    }
+    return n;
+}
+
+#if !DEBUG
+static inline void dump_all_fds(const char *extra_msg) {}
+#else
+static void dump_all_fds(const char *extra_msg)
+{
+int i;
+    fdevent *fde;
+    // per fd: 4 digits (but really: log10(FD_SETSIZE)), 1 staus, 1 blank
+    char msg_buff[FD_SETSIZE*6 + 1], *pb=msg_buff;
+    size_t max_chars = FD_SETSIZE * 6 + 1;
+    int printed_out;
+#define SAFE_SPRINTF(...)                                                    \
+    do {                                                                     \
+        printed_out = snprintf(pb, max_chars, __VA_ARGS__);                  \
+        if (printed_out <= 0) {                                              \
+            D("... snprintf failed.\n");                                     \
+            return;                                                          \
+        }                                                                    \
+        if (max_chars < (unsigned int)printed_out) {                         \
+            D("... snprintf out of space.\n");                               \
+            return;                                                          \
+        }                                                                    \
+        pb += printed_out;                                                   \
+        max_chars -= printed_out;                                            \
+    } while(0)
+
+    for(i = 0; i < select_n; i++) {
+        fde = fd_table[i];
+        SAFE_SPRINTF("%d", i);
+        if(fde == 0) {
+            SAFE_SPRINTF("? ");
+            continue;
+        }
+        if(fcntl(i, F_GETFL, NULL) < 0) {
+            SAFE_SPRINTF("b");
+        }
+        SAFE_SPRINTF(" ");
+    }
+    D("%s fd_table[]->fd = {%s}\n", extra_msg, msg_buff);
+}
+#endif
+
+static void fdevent_process()
+{
+    int i, n;
+    fdevent *fde;
+    unsigned events;
+    fd_set rfd, wfd, efd;
+
+    memcpy(&rfd, &read_fds, sizeof(fd_set));
+    memcpy(&wfd, &write_fds, sizeof(fd_set));
+    memcpy(&efd, &error_fds, sizeof(fd_set));
+
+    dump_all_fds("pre select()");
+
+    n = select(select_n, &rfd, &wfd, &efd, NULL);
+    int saved_errno = errno;
+    D("select() returned n=%d, errno=%d\n", n, n<0?saved_errno:0);
+
+    dump_all_fds("post select()");
+
+    if(n < 0) {
+        switch(saved_errno) {
+        case EINTR: return;
+        case EBADF:
+            // Can't trust the FD sets after an error.
+            FD_ZERO(&wfd);
+            FD_ZERO(&efd);
+            FD_ZERO(&rfd);
+            break;
+        default:
+            D("Unexpected select() error=%d\n", saved_errno);
+            return;
+        }
+    }
+    if(n <= 0) {
+        // We fake a read, as the rest of the code assumes
+        // that errors will be detected at that point.
+        n = fdevent_fd_check(&rfd);
+    }
+
+    for(i = 0; (i < select_n) && (n > 0); i++) {
+        events = 0;
+        if(FD_ISSET(i, &rfd)) { events |= FDE_READ; n--; }
+        if(FD_ISSET(i, &wfd)) { events |= FDE_WRITE; n--; }
+        if(FD_ISSET(i, &efd)) { events |= FDE_ERROR; n--; }
+
+        if(events) {
+            fde = fd_table[i];
+            if(fde == 0)
+              FATAL("missing fde for fd %d\n", i);
+
+            fde->events |= events;
+
+            D("got events fde->fd=%d events=%04x, state=%04x\n",
+                fde->fd, fde->events, fde->state);
+            if(fde->state & FDE_PENDING) continue;
+            fde->state |= FDE_PENDING;
+            fdevent_plist_enqueue(fde);
+        }
+    }
+}
+
+#endif
+
+static void fdevent_register(fdevent *fde)
+{
+    if(fde->fd < 0) {
+        FATAL("bogus negative fd (%d)\n", fde->fd);
+    }
+
+    if(fde->fd >= fd_table_max) {
+        int oldmax = fd_table_max;
+        if(fde->fd > 32000) {
+            FATAL("bogus huuuuge fd (%d)\n", fde->fd);
+        }
+        if(fd_table_max == 0) {
+            fdevent_init();
+            fd_table_max = 256;
+        }
+        while(fd_table_max <= fde->fd) {
+            fd_table_max *= 2;
+        }
+        fd_table = realloc(fd_table, sizeof(fdevent*) * fd_table_max);
+        if(fd_table == 0) {
+            FATAL("could not expand fd_table to %d entries\n", fd_table_max);
+        }
+        memset(fd_table + oldmax, 0, sizeof(int) * (fd_table_max - oldmax));
+    }
+
+    fd_table[fde->fd] = fde;
+}
+
+static void fdevent_unregister(fdevent *fde)
+{
+    if((fde->fd < 0) || (fde->fd >= fd_table_max)) {
+        FATAL("fd out of range (%d)\n", fde->fd);
+    }
+
+    if(fd_table[fde->fd] != fde) {
+        FATAL("fd_table out of sync [%d]\n", fde->fd);
+    }
+
+    fd_table[fde->fd] = 0;
+
+    if(!(fde->state & FDE_DONT_CLOSE)) {
+        dump_fde(fde, "close");
+        adb_close(fde->fd);
+    }
+}
+
+static void fdevent_plist_enqueue(fdevent *node)
+{
+    fdevent *list = &list_pending;
+
+    node->next = list;
+    node->prev = list->prev;
+    node->prev->next = node;
+    list->prev = node;
+}
+
+static void fdevent_plist_remove(fdevent *node)
+{
+    node->prev->next = node->next;
+    node->next->prev = node->prev;
+    node->next = 0;
+    node->prev = 0;
+}
+
+static fdevent *fdevent_plist_dequeue(void)
+{
+    fdevent *list = &list_pending;
+    fdevent *node = list->next;
+
+    if(node == list) return 0;
+
+    list->next = node->next;
+    list->next->prev = list;
+    node->next = 0;
+    node->prev = 0;
+
+    return node;
+}
+
+static void fdevent_call_fdfunc(fdevent* fde)
+{
+    unsigned events = fde->events;
+    fde->events = 0;
+    if(!(fde->state & FDE_PENDING)) return;
+    fde->state &= (~FDE_PENDING);
+    dump_fde(fde, "callback");
+    fde->func(fde->fd, events, fde->arg);
+}
+
+static void fdevent_subproc_event_func(int fd, unsigned ev, void *userdata)
+{
+
+    D("subproc handling on fd=%d ev=%04x\n", fd, ev);
+
+    // Hook oneself back into the fde's suitable for select() on read.
+    if((fd < 0) || (fd >= fd_table_max)) {
+        FATAL("fd %d out of range for fd_table \n", fd);
+    }
+    fdevent *fde = fd_table[fd];
+    fdevent_add(fde, FDE_READ);
+
+    if(ev & FDE_READ){
+      int subproc_fd;
+
+      if(readx(fd, &subproc_fd, sizeof(subproc_fd))) {
+          FATAL("Failed to read the subproc's fd from fd=%d\n", fd);
+      }
+      if((subproc_fd < 0) || (subproc_fd >= fd_table_max)) {
+          D("subproc_fd %d out of range 0, fd_table_max=%d\n",
+            subproc_fd, fd_table_max);
+          return;
+      }
+      fdevent *subproc_fde = fd_table[subproc_fd];
+      if(!subproc_fde) {
+          D("subproc_fd %d cleared from fd_table\n", subproc_fd);
+          return;
+      }
+      if(subproc_fde->fd != subproc_fd) {
+          // Already reallocated?
+          D("subproc_fd %d != fd_table[].fd %d\n", subproc_fd, subproc_fde->fd);
+          return;
+      }
+
+      subproc_fde->force_eof = 1;
+
+      int rcount = 0;
+      ioctl(subproc_fd, FIONREAD, &rcount);
+      D("subproc with fd=%d  has rcount=%d err=%d\n",
+        subproc_fd, rcount, errno);
+
+      if(rcount) {
+        // If there is data left, it will show up in the select().
+        // This works because there is no other thread reading that
+        // data when in this fd_func().
+        return;
+      }
+
+      D("subproc_fde.state=%04x\n", subproc_fde->state);
+      subproc_fde->events |= FDE_READ;
+      if(subproc_fde->state & FDE_PENDING) {
+        return;
+      }
+      subproc_fde->state |= FDE_PENDING;
+      fdevent_call_fdfunc(subproc_fde);
+    }
+}
+
+fdevent *fdevent_create(int fd, fd_func func, void *arg)
+{
+    fdevent *fde = (fdevent*) malloc(sizeof(fdevent));
+    if(fde == 0) return 0;
+    fdevent_install(fde, fd, func, arg);
+    fde->state |= FDE_CREATED;
+    return fde;
+}
+
+void fdevent_destroy(fdevent *fde)
+{
+    if(fde == 0) return;
+    if(!(fde->state & FDE_CREATED)) {
+        FATAL("fde %p not created by fdevent_create()\n", fde);
+    }
+    fdevent_remove(fde);
+}
+
+void fdevent_install(fdevent *fde, int fd, fd_func func, void *arg)
+{
+    memset(fde, 0, sizeof(fdevent));
+    fde->state = FDE_ACTIVE;
+    fde->fd = fd;
+    fde->force_eof = 0;
+    fde->func = func;
+    fde->arg = arg;
+
+#ifndef HAVE_WINSOCK
+    fcntl(fd, F_SETFL, O_NONBLOCK);
+#endif
+    fdevent_register(fde);
+    dump_fde(fde, "connect");
+    fdevent_connect(fde);
+    fde->state |= FDE_ACTIVE;
+}
+
+void fdevent_remove(fdevent *fde)
+{
+    if(fde->state & FDE_PENDING) {
+        fdevent_plist_remove(fde);
+    }
+
+    if(fde->state & FDE_ACTIVE) {
+        fdevent_disconnect(fde);
+        dump_fde(fde, "disconnect");
+        fdevent_unregister(fde);
+    }
+
+    fde->state = 0;
+    fde->events = 0;
+}
+
+
+void fdevent_set(fdevent *fde, unsigned events)
+{
+    events &= FDE_EVENTMASK;
+
+    if((fde->state & FDE_EVENTMASK) == events) return;
+
+    if(fde->state & FDE_ACTIVE) {
+        fdevent_update(fde, events);
+        dump_fde(fde, "update");
+    }
+
+    fde->state = (fde->state & FDE_STATEMASK) | events;
+
+    if(fde->state & FDE_PENDING) {
+            /* if we're pending, make sure
+            ** we don't signal an event that
+            ** is no longer wanted.
+            */
+        fde->events &= (~events);
+        if(fde->events == 0) {
+            fdevent_plist_remove(fde);
+            fde->state &= (~FDE_PENDING);
+        }
+    }
+}
+
+void fdevent_add(fdevent *fde, unsigned events)
+{
+    fdevent_set(
+        fde, (fde->state & FDE_EVENTMASK) | (events & FDE_EVENTMASK));
+}
+
+void fdevent_del(fdevent *fde, unsigned events)
+{
+    fdevent_set(
+        fde, (fde->state & FDE_EVENTMASK) & (~(events & FDE_EVENTMASK)));
+}
+
+void fdevent_subproc_setup()
+{
+    int s[2];
+
+    if(adb_socketpair(s)) {
+        FATAL("cannot create shell-exit socket-pair\n");
+    }
+    SHELL_EXIT_NOTIFY_FD = s[0];
+    fdevent *fde;
+    fde = fdevent_create(s[1], fdevent_subproc_event_func, NULL);
+    if(!fde)
+      FATAL("cannot create fdevent for shell-exit handler\n");
+    fdevent_add(fde, FDE_READ);
+}
+
+void fdevent_loop()
+{
+    fdevent *fde;
+    fdevent_subproc_setup();
+
+    for(;;) {
+        D("--- ---- waiting for events\n");
+
+        fdevent_process();
+
+        while((fde = fdevent_plist_dequeue())) {
+            fdevent_call_fdfunc(fde);
+        }
+    }
+}
diff --git a/package/utils/adbd/src/adb/fdevent.h b/package/utils/adbd/src/adb/fdevent.h
new file mode 100644
index 0000000..a0ebe2a
--- /dev/null
+++ b/package/utils/adbd/src/adb/fdevent.h
@@ -0,0 +1,83 @@
+/*
+ * 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 __FDEVENT_H
+#define __FDEVENT_H
+
+#include <stdint.h>  /* for int64_t */
+
+/* events that may be observed */
+#define FDE_READ              0x0001
+#define FDE_WRITE             0x0002
+#define FDE_ERROR             0x0004
+#define FDE_TIMEOUT           0x0008
+
+/* features that may be set (via the events set/add/del interface) */
+#define FDE_DONT_CLOSE        0x0080
+
+typedef struct fdevent fdevent;
+
+typedef void (*fd_func)(int fd, unsigned events, void *userdata);
+
+/* Allocate and initialize a new fdevent object
+ * Note: use FD_TIMER as 'fd' to create a fd-less object
+ * (used to implement timers).
+*/
+fdevent *fdevent_create(int fd, fd_func func, void *arg);
+
+/* Uninitialize and deallocate an fdevent object that was
+** created by fdevent_create()
+*/
+void fdevent_destroy(fdevent *fde);
+
+/* Initialize an fdevent object that was externally allocated
+*/
+void fdevent_install(fdevent *fde, int fd, fd_func func, void *arg);
+
+/* Uninitialize an fdevent object that was initialized by
+** fdevent_install()
+*/
+void fdevent_remove(fdevent *item);
+
+/* Change which events should cause notifications
+*/
+void fdevent_set(fdevent *fde, unsigned events);
+void fdevent_add(fdevent *fde, unsigned events);
+void fdevent_del(fdevent *fde, unsigned events);
+
+void fdevent_set_timeout(fdevent *fde, int64_t  timeout_ms);
+
+/* loop forever, handling events.
+*/
+void fdevent_loop();
+
+struct fdevent 
+{
+    fdevent *next;
+    fdevent *prev;
+
+    int fd;
+    int force_eof;
+
+    unsigned short state;
+    unsigned short events;
+
+    fd_func func;
+    void *arg;
+};
+
+
+#endif
diff --git a/package/utils/adbd/src/adb/file_sync_client.c b/package/utils/adbd/src/adb/file_sync_client.c
new file mode 100644
index 0000000..d3cb113
--- /dev/null
+++ b/package/utils/adbd/src/adb/file_sync_client.c
@@ -0,0 +1,1089 @@
+/*
+ * 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 <errno.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <time.h>
+#include <dirent.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <zipfile/zipfile.h>
+#include <utime.h>
+
+#include "sysdeps.h"
+#include "adb.h"
+#include "adb_client.h"
+#include "file_sync_service.h"
+
+
+static unsigned long long total_bytes;
+static long long start_time;
+
+static long long NOW()
+{
+    struct timeval tv;
+    gettimeofday(&tv, 0);
+    return ((long long) tv.tv_usec) +
+        1000000LL * ((long long) tv.tv_sec);
+}
+
+static void BEGIN()
+{
+    total_bytes = 0;
+    start_time = NOW();
+}
+
+static void END()
+{
+    long long t = NOW() - start_time;
+    if(total_bytes == 0) return;
+
+    if (t == 0)  /* prevent division by 0 :-) */
+        t = 1000000;
+
+    fprintf(stderr,"%lld KB/s (%lld bytes in %lld.%03llds)\n",
+            ((total_bytes * 1000000LL) / t) / 1024LL,
+            total_bytes, (t / 1000000LL), (t % 1000000LL) / 1000LL);
+}
+
+static const char* transfer_progress_format = "\rTransferring: %llu/%llu (%d%%)";
+
+static void print_transfer_progress(unsigned long long bytes_current,
+                                    unsigned long long bytes_total) {
+    if (bytes_total == 0) return;
+
+    fprintf(stderr, transfer_progress_format, bytes_current, bytes_total,
+            (int) (bytes_current * 100 / bytes_total));
+
+    if (bytes_current == bytes_total) {
+        fputc('\n', stderr);
+    }
+
+    fflush(stderr);
+}
+
+void sync_quit(int fd)
+{
+    syncmsg msg;
+
+    msg.req.id = ID_QUIT;
+    msg.req.namelen = 0;
+
+    writex(fd, &msg.req, sizeof(msg.req));
+}
+
+typedef void (*sync_ls_cb)(unsigned mode, unsigned size, unsigned time, const char *name, void *cookie);
+
+int sync_ls(int fd, const char *path, sync_ls_cb func, void *cookie)
+{
+    syncmsg msg;
+    char buf[257];
+    int len;
+
+    len = strlen(path);
+    if(len > 1024) goto fail;
+
+    msg.req.id = ID_LIST;
+    msg.req.namelen = htoll(len);
+
+    if(writex(fd, &msg.req, sizeof(msg.req)) ||
+       writex(fd, path, len)) {
+        goto fail;
+    }
+
+    for(;;) {
+        if(readx(fd, &msg.dent, sizeof(msg.dent))) break;
+        if(msg.dent.id == ID_DONE) return 0;
+        if(msg.dent.id != ID_DENT) break;
+
+        len = ltohl(msg.dent.namelen);
+        if(len > 256) break;
+
+        if(readx(fd, buf, len)) break;
+        buf[len] = 0;
+
+        func(ltohl(msg.dent.mode),
+             ltohl(msg.dent.size),
+             ltohl(msg.dent.time),
+             buf, cookie);
+    }
+
+fail:
+    adb_close(fd);
+    return -1;
+}
+
+typedef struct syncsendbuf syncsendbuf;
+
+struct syncsendbuf {
+    unsigned id;
+    unsigned size;
+    char data[SYNC_DATA_MAX];
+};
+
+static syncsendbuf send_buffer;
+
+int sync_readtime(int fd, const char *path, unsigned int *timestamp,
+                  unsigned int *mode)
+{
+    syncmsg msg;
+    int len = strlen(path);
+
+    msg.req.id = ID_STAT;
+    msg.req.namelen = htoll(len);
+
+    if(writex(fd, &msg.req, sizeof(msg.req)) ||
+       writex(fd, path, len)) {
+        return -1;
+    }
+
+    if(readx(fd, &msg.stat, sizeof(msg.stat))) {
+        return -1;
+    }
+
+    if(msg.stat.id != ID_STAT) {
+        return -1;
+    }
+
+    *timestamp = ltohl(msg.stat.time);
+    *mode = ltohl(msg.stat.mode);
+    return 0;
+}
+
+static int sync_start_readtime(int fd, const char *path)
+{
+    syncmsg msg;
+    int len = strlen(path);
+
+    msg.req.id = ID_STAT;
+    msg.req.namelen = htoll(len);
+
+    if(writex(fd, &msg.req, sizeof(msg.req)) ||
+       writex(fd, path, len)) {
+        return -1;
+    }
+
+    return 0;
+}
+
+static int sync_finish_readtime(int fd, unsigned int *timestamp,
+                                unsigned int *mode, unsigned int *size)
+{
+    syncmsg msg;
+
+    if(readx(fd, &msg.stat, sizeof(msg.stat)))
+        return -1;
+
+    if(msg.stat.id != ID_STAT)
+        return -1;
+
+    *timestamp = ltohl(msg.stat.time);
+    *mode = ltohl(msg.stat.mode);
+    *size = ltohl(msg.stat.size);
+
+    return 0;
+}
+
+int sync_readmode(int fd, const char *path, unsigned *mode)
+{
+    syncmsg msg;
+    int len = strlen(path);
+
+    msg.req.id = ID_STAT;
+    msg.req.namelen = htoll(len);
+
+    if(writex(fd, &msg.req, sizeof(msg.req)) ||
+       writex(fd, path, len)) {
+        return -1;
+    }
+
+    if(readx(fd, &msg.stat, sizeof(msg.stat))) {
+        return -1;
+    }
+
+    if(msg.stat.id != ID_STAT) {
+        return -1;
+    }
+
+    *mode = ltohl(msg.stat.mode);
+    return 0;
+}
+
+static int write_data_file(int fd, const char *path, syncsendbuf *sbuf, int show_progress)
+{
+    int lfd, err = 0;
+    unsigned long long size = 0;
+
+    lfd = adb_open(path, O_RDONLY);
+    if(lfd < 0) {
+        fprintf(stderr,"cannot open '%s': %s\n", path, strerror(errno));
+        return -1;
+    }
+
+    if (show_progress) {
+        // Determine local file size.
+        struct stat st;
+        if (fstat(lfd, &st)) {
+            fprintf(stderr,"cannot stat '%s': %s\n", path, strerror(errno));
+            return -1;
+        }
+
+        size = st.st_size;
+    }
+
+    sbuf->id = ID_DATA;
+    for(;;) {
+        int ret;
+
+        ret = adb_read(lfd, sbuf->data, SYNC_DATA_MAX);
+        if(!ret)
+            break;
+
+        if(ret < 0) {
+            if(errno == EINTR)
+                continue;
+            fprintf(stderr,"cannot read '%s': %s\n", path, strerror(errno));
+            break;
+        }
+
+        sbuf->size = htoll(ret);
+        if(writex(fd, sbuf, sizeof(unsigned) * 2 + ret)){
+            err = -1;
+            break;
+        }
+        total_bytes += ret;
+
+        if (show_progress) {
+            print_transfer_progress(total_bytes, size);
+        }
+    }
+
+    adb_close(lfd);
+    return err;
+}
+
+static int write_data_buffer(int fd, char* file_buffer, int size, syncsendbuf *sbuf,
+                             int show_progress)
+{
+    int err = 0;
+    int total = 0;
+
+    sbuf->id = ID_DATA;
+    while (total < size) {
+        int count = size - total;
+        if (count > SYNC_DATA_MAX) {
+            count = SYNC_DATA_MAX;
+        }
+
+        memcpy(sbuf->data, &file_buffer[total], count);
+        sbuf->size = htoll(count);
+        if(writex(fd, sbuf, sizeof(unsigned) * 2 + count)){
+            err = -1;
+            break;
+        }
+        total += count;
+        total_bytes += count;
+
+        if (show_progress) {
+            print_transfer_progress(total, size);
+        }
+    }
+
+    return err;
+}
+
+#ifdef HAVE_SYMLINKS
+static int write_data_link(int fd, const char *path, syncsendbuf *sbuf)
+{
+    int len, ret;
+
+    len = readlink(path, sbuf->data, SYNC_DATA_MAX-1);
+    if(len < 0) {
+        fprintf(stderr, "error reading link '%s': %s\n", path, strerror(errno));
+        return -1;
+    }
+    sbuf->data[len] = '\0';
+
+    sbuf->size = htoll(len + 1);
+    sbuf->id = ID_DATA;
+
+    ret = writex(fd, sbuf, sizeof(unsigned) * 2 + len + 1);
+    if(ret)
+        return -1;
+
+    total_bytes += len + 1;
+
+    return 0;
+}
+#endif
+
+static int sync_send(int fd, const char *lpath, const char *rpath,
+                     unsigned mtime, mode_t mode, int verifyApk, int show_progress)
+{
+    syncmsg msg;
+    int len, r;
+    syncsendbuf *sbuf = &send_buffer;
+    char* file_buffer = NULL;
+    int size = 0;
+    char tmp[64];
+
+    len = strlen(rpath);
+    if(len > 1024) goto fail;
+
+    snprintf(tmp, sizeof(tmp), ",%d", mode);
+    r = strlen(tmp);
+
+    if (verifyApk) {
+        int lfd;
+        zipfile_t zip;
+        zipentry_t entry;
+        int amt;
+
+        // if we are transferring an APK file, then sanity check to make sure
+        // we have a real zip file that contains an AndroidManifest.xml
+        // this requires that we read the entire file into memory.
+        lfd = adb_open(lpath, O_RDONLY);
+        if(lfd < 0) {
+            fprintf(stderr,"cannot open '%s': %s\n", lpath, strerror(errno));
+            return -1;
+        }
+
+        size = adb_lseek(lfd, 0, SEEK_END);
+        if (size == -1 || -1 == adb_lseek(lfd, 0, SEEK_SET)) {
+            fprintf(stderr, "error seeking in file '%s'\n", lpath);
+            adb_close(lfd);
+            return 1;
+        }
+
+        file_buffer = (char *)malloc(size);
+        if (file_buffer == NULL) {
+            fprintf(stderr, "could not allocate buffer for '%s'\n",
+                    lpath);
+            adb_close(lfd);
+            return 1;
+        }
+        amt = adb_read(lfd, file_buffer, size);
+        if (amt != size) {
+            fprintf(stderr, "error reading from file: '%s'\n", lpath);
+            adb_close(lfd);
+            free(file_buffer);
+            return 1;
+        }
+
+        adb_close(lfd);
+
+        zip = init_zipfile(file_buffer, size);
+        if (zip == NULL) {
+            fprintf(stderr, "file '%s' is not a valid zip file\n",
+                    lpath);
+            free(file_buffer);
+            return 1;
+        }
+
+        entry = lookup_zipentry(zip, "AndroidManifest.xml");
+        release_zipfile(zip);
+        if (entry == NULL) {
+            fprintf(stderr, "file '%s' does not contain AndroidManifest.xml\n",
+                    lpath);
+            free(file_buffer);
+            return 1;
+        }
+    }
+
+    msg.req.id = ID_SEND;
+    msg.req.namelen = htoll(len + r);
+
+    if(writex(fd, &msg.req, sizeof(msg.req)) ||
+       writex(fd, rpath, len) || writex(fd, tmp, r)) {
+        free(file_buffer);
+        goto fail;
+    }
+
+    if (file_buffer) {
+        write_data_buffer(fd, file_buffer, size, sbuf, show_progress);
+        free(file_buffer);
+    } else if (S_ISREG(mode))
+        write_data_file(fd, lpath, sbuf, show_progress);
+#ifdef HAVE_SYMLINKS
+    else if (S_ISLNK(mode))
+        write_data_link(fd, lpath, sbuf);
+#endif
+    else
+        goto fail;
+
+    msg.data.id = ID_DONE;
+    msg.data.size = htoll(mtime);
+    if(writex(fd, &msg.data, sizeof(msg.data)))
+        goto fail;
+
+    if(readx(fd, &msg.status, sizeof(msg.status)))
+        return -1;
+
+    if(msg.status.id != ID_OKAY) {
+        if(msg.status.id == ID_FAIL) {
+            len = ltohl(msg.status.msglen);
+            if(len > 256) len = 256;
+            if(readx(fd, sbuf->data, len)) {
+                return -1;
+            }
+            sbuf->data[len] = 0;
+        } else
+            strcpy(sbuf->data, "unknown reason");
+
+        fprintf(stderr,"failed to copy '%s' to '%s': %s\n", lpath, rpath, sbuf->data);
+        return -1;
+    }
+
+    return 0;
+
+fail:
+    fprintf(stderr,"protocol failure\n");
+    adb_close(fd);
+    return -1;
+}
+
+static int mkdirs(const char *name)
+{
+    int ret;
+    char *x = (char *)name + 1;
+
+    for(;;) {
+        x = adb_dirstart(x);
+        if(x == 0) return 0;
+        *x = 0;
+        ret = adb_mkdir(name, 0775);
+        *x = OS_PATH_SEPARATOR;
+        if((ret < 0) && (errno != EEXIST)) {
+            return ret;
+        }
+        x++;
+    }
+    return 0;
+}
+
+int sync_recv(int fd, const char *rpath, const char *lpath, int show_progress)
+{
+    syncmsg msg;
+    int len;
+    int lfd = -1;
+    char *buffer = send_buffer.data;
+    unsigned id;
+    unsigned long long size = 0;
+
+    len = strlen(rpath);
+    if(len > 1024) return -1;
+
+    if (show_progress) {
+        // Determine remote file size.
+        syncmsg stat_msg;
+        stat_msg.req.id = ID_STAT;
+        stat_msg.req.namelen = htoll(len);
+
+        if (writex(fd, &stat_msg.req, sizeof(stat_msg.req)) ||
+            writex(fd, rpath, len)) {
+            return -1;
+        }
+
+        if (readx(fd, &stat_msg.stat, sizeof(stat_msg.stat))) {
+            return -1;
+        }
+
+        if (stat_msg.stat.id != ID_STAT) return -1;
+
+        size = ltohl(stat_msg.stat.size);
+    }
+
+    msg.req.id = ID_RECV;
+    msg.req.namelen = htoll(len);
+    if(writex(fd, &msg.req, sizeof(msg.req)) ||
+       writex(fd, rpath, len)) {
+        return -1;
+    }
+
+    if(readx(fd, &msg.data, sizeof(msg.data))) {
+        return -1;
+    }
+    id = msg.data.id;
+
+    if((id == ID_DATA) || (id == ID_DONE)) {
+        adb_unlink(lpath);
+        mkdirs(lpath);
+        lfd = adb_creat(lpath, 0644);
+        if(lfd < 0) {
+            fprintf(stderr,"cannot create '%s': %s\n", lpath, strerror(errno));
+            return -1;
+        }
+        goto handle_data;
+    } else {
+        goto remote_error;
+    }
+
+    for(;;) {
+        if(readx(fd, &msg.data, sizeof(msg.data))) {
+            return -1;
+        }
+        id = msg.data.id;
+
+    handle_data:
+        len = ltohl(msg.data.size);
+        if(id == ID_DONE) break;
+        if(id != ID_DATA) goto remote_error;
+        if(len > SYNC_DATA_MAX) {
+            fprintf(stderr,"data overrun\n");
+            adb_close(lfd);
+            return -1;
+        }
+
+        if(readx(fd, buffer, len)) {
+            adb_close(lfd);
+            return -1;
+        }
+
+        if(writex(lfd, buffer, len)) {
+            fprintf(stderr,"cannot write '%s': %s\n", rpath, strerror(errno));
+            adb_close(lfd);
+            return -1;
+        }
+
+        total_bytes += len;
+
+        if (show_progress) {
+            print_transfer_progress(total_bytes, size);
+        }
+    }
+
+    adb_close(lfd);
+    return 0;
+
+remote_error:
+    adb_close(lfd);
+    adb_unlink(lpath);
+
+    if(id == ID_FAIL) {
+        len = ltohl(msg.data.size);
+        if(len > 256) len = 256;
+        if(readx(fd, buffer, len)) {
+            return -1;
+        }
+        buffer[len] = 0;
+    } else {
+        memcpy(buffer, &id, 4);
+        buffer[4] = 0;
+//        strcpy(buffer,"unknown reason");
+    }
+    fprintf(stderr,"failed to copy '%s' to '%s': %s\n", rpath, lpath, buffer);
+    return 0;
+}
+
+
+
+/* --- */
+
+
+static void do_sync_ls_cb(unsigned mode, unsigned size, unsigned time,
+                          const char *name, void *cookie)
+{
+    printf("%08x %08x %08x %s\n", mode, size, time, name);
+}
+
+int do_sync_ls(const char *path)
+{
+    int fd = adb_connect("sync:");
+    if(fd < 0) {
+        fprintf(stderr,"error: %s\n", adb_error());
+        return 1;
+    }
+
+    if(sync_ls(fd, path, do_sync_ls_cb, 0)) {
+        return 1;
+    } else {
+        sync_quit(fd);
+        return 0;
+    }
+}
+
+typedef struct copyinfo copyinfo;
+
+struct copyinfo
+{
+    copyinfo *next;
+    const char *src;
+    const char *dst;
+    unsigned int time;
+    unsigned int mode;
+    unsigned int size;
+    int flag;
+    //char data[0];
+};
+
+copyinfo *mkcopyinfo(const char *spath, const char *dpath,
+                     const char *name, int isdir)
+{
+    int slen = strlen(spath);
+    int dlen = strlen(dpath);
+    int nlen = strlen(name);
+    int ssize = slen + nlen + 2;
+    int dsize = dlen + nlen + 2;
+
+    copyinfo *ci = malloc(sizeof(copyinfo) + ssize + dsize);
+    if(ci == 0) {
+        fprintf(stderr,"out of memory\n");
+        abort();
+    }
+
+    ci->next = 0;
+    ci->time = 0;
+    ci->mode = 0;
+    ci->size = 0;
+    ci->flag = 0;
+    ci->src = (const char*)(ci + 1);
+    ci->dst = ci->src + ssize;
+    snprintf((char*) ci->src, ssize, isdir ? "%s%s/" : "%s%s", spath, name);
+    snprintf((char*) ci->dst, dsize, isdir ? "%s%s/" : "%s%s", dpath, name);
+
+//    fprintf(stderr,"mkcopyinfo('%s','%s')\n", ci->src, ci->dst);
+    return ci;
+}
+
+
+static int local_build_list(copyinfo **filelist,
+                            const char *lpath, const char *rpath)
+{
+    DIR *d;
+    struct dirent *de;
+    struct stat st;
+    copyinfo *dirlist = 0;
+    copyinfo *ci, *next;
+
+//    fprintf(stderr,"local_build_list('%s','%s')\n", lpath, rpath);
+
+    d = opendir(lpath);
+    if(d == 0) {
+        fprintf(stderr,"cannot open '%s': %s\n", lpath, strerror(errno));
+        return -1;
+    }
+
+    while((de = readdir(d))) {
+        char stat_path[PATH_MAX];
+        char *name = de->d_name;
+
+        if(name[0] == '.') {
+            if(name[1] == 0) continue;
+            if((name[1] == '.') && (name[2] == 0)) continue;
+        }
+
+        /*
+         * We could use d_type if HAVE_DIRENT_D_TYPE is defined, but reiserfs
+         * always returns DT_UNKNOWN, so we just use stat() for all cases.
+         */
+        if (strlen(lpath) + strlen(de->d_name) + 1 > sizeof(stat_path))
+            continue;
+        strcpy(stat_path, lpath);
+        strcat(stat_path, de->d_name);
+        stat(stat_path, &st);
+
+        if (S_ISDIR(st.st_mode)) {
+            ci = mkcopyinfo(lpath, rpath, name, 1);
+            ci->next = dirlist;
+            dirlist = ci;
+        } else {
+            ci = mkcopyinfo(lpath, rpath, name, 0);
+            if(lstat(ci->src, &st)) {
+                fprintf(stderr,"cannot stat '%s': %s\n", ci->src, strerror(errno));
+                free(ci);
+                closedir(d);
+                return -1;
+            }
+            if(!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode)) {
+                fprintf(stderr, "skipping special file '%s'\n", ci->src);
+                free(ci);
+            } else {
+                ci->time = st.st_mtime;
+                ci->mode = st.st_mode;
+                ci->size = st.st_size;
+                ci->next = *filelist;
+                *filelist = ci;
+            }
+        }
+    }
+
+    closedir(d);
+
+    for(ci = dirlist; ci != 0; ci = next) {
+        next = ci->next;
+        local_build_list(filelist, ci->src, ci->dst);
+        free(ci);
+    }
+
+    return 0;
+}
+
+
+static int copy_local_dir_remote(int fd, const char *lpath, const char *rpath, int checktimestamps, int listonly)
+{
+    copyinfo *filelist = 0;
+    copyinfo *ci, *next;
+    int pushed = 0;
+    int skipped = 0;
+
+    if((lpath[0] == 0) || (rpath[0] == 0)) return -1;
+    if(lpath[strlen(lpath) - 1] != '/') {
+        int  tmplen = strlen(lpath)+2;
+        char *tmp = malloc(tmplen);
+        if(tmp == 0) return -1;
+        snprintf(tmp, tmplen, "%s/",lpath);
+        lpath = tmp;
+    }
+    if(rpath[strlen(rpath) - 1] != '/') {
+        int tmplen = strlen(rpath)+2;
+        char *tmp = malloc(tmplen);
+        if(tmp == 0) return -1;
+        snprintf(tmp, tmplen, "%s/",rpath);
+        rpath = tmp;
+    }
+
+    if(local_build_list(&filelist, lpath, rpath)) {
+        return -1;
+    }
+
+    if(checktimestamps){
+        for(ci = filelist; ci != 0; ci = ci->next) {
+            if(sync_start_readtime(fd, ci->dst)) {
+                return 1;
+            }
+        }
+        for(ci = filelist; ci != 0; ci = ci->next) {
+            unsigned int timestamp, mode, size;
+            if(sync_finish_readtime(fd, &timestamp, &mode, &size))
+                return 1;
+            if(size == ci->size) {
+                /* for links, we cannot update the atime/mtime */
+                if((S_ISREG(ci->mode & mode) && timestamp == ci->time) ||
+                    (S_ISLNK(ci->mode & mode) && timestamp >= ci->time))
+                    ci->flag = 1;
+            }
+        }
+    }
+    for(ci = filelist; ci != 0; ci = next) {
+        next = ci->next;
+        if(ci->flag == 0) {
+            fprintf(stderr,"%spush: %s -> %s\n", listonly ? "would " : "", ci->src, ci->dst);
+            if(!listonly &&
+               sync_send(fd, ci->src, ci->dst, ci->time, ci->mode, 0 /* no verify APK */,
+                         0 /* no show progress */)) {
+                return 1;
+            }
+            pushed++;
+        } else {
+            skipped++;
+        }
+        free(ci);
+    }
+
+    fprintf(stderr,"%d file%s pushed. %d file%s skipped.\n",
+            pushed, (pushed == 1) ? "" : "s",
+            skipped, (skipped == 1) ? "" : "s");
+
+    return 0;
+}
+
+
+int do_sync_push(const char *lpath, const char *rpath, int verifyApk, int show_progress)
+{
+    struct stat st;
+    unsigned mode;
+    int fd;
+
+    fd = adb_connect("sync:");
+    if(fd < 0) {
+        fprintf(stderr,"error: %s\n", adb_error());
+        return 1;
+    }
+
+    if(stat(lpath, &st)) {
+        fprintf(stderr,"cannot stat '%s': %s\n", lpath, strerror(errno));
+        sync_quit(fd);
+        return 1;
+    }
+
+    if(S_ISDIR(st.st_mode)) {
+        BEGIN();
+        if(copy_local_dir_remote(fd, lpath, rpath, 0, 0)) {
+            return 1;
+        } else {
+            END();
+            sync_quit(fd);
+        }
+    } else {
+        if(sync_readmode(fd, rpath, &mode)) {
+            return 1;
+        }
+        if((mode != 0) && S_ISDIR(mode)) {
+                /* if we're copying a local file to a remote directory,
+                ** we *really* want to copy to remotedir + "/" + localfilename
+                */
+            const char *name = adb_dirstop(lpath);
+            if(name == 0) {
+                name = lpath;
+            } else {
+                name++;
+            }
+            int  tmplen = strlen(name) + strlen(rpath) + 2;
+            char *tmp = malloc(strlen(name) + strlen(rpath) + 2);
+            if(tmp == 0) return 1;
+            snprintf(tmp, tmplen, "%s/%s", rpath, name);
+            rpath = tmp;
+        }
+        BEGIN();
+        if(sync_send(fd, lpath, rpath, st.st_mtime, st.st_mode, verifyApk, show_progress)) {
+            return 1;
+        } else {
+            END();
+            sync_quit(fd);
+            return 0;
+        }
+    }
+
+    return 0;
+}
+
+
+typedef struct {
+    copyinfo **filelist;
+    copyinfo **dirlist;
+    const char *rpath;
+    const char *lpath;
+} sync_ls_build_list_cb_args;
+
+void
+sync_ls_build_list_cb(unsigned mode, unsigned size, unsigned time,
+                      const char *name, void *cookie)
+{
+    sync_ls_build_list_cb_args *args = (sync_ls_build_list_cb_args *)cookie;
+    copyinfo *ci;
+
+    if (S_ISDIR(mode)) {
+        copyinfo **dirlist = args->dirlist;
+
+        /* Don't try recursing down "." or ".." */
+        if (name[0] == '.') {
+            if (name[1] == '\0') return;
+            if ((name[1] == '.') && (name[2] == '\0')) return;
+        }
+
+        ci = mkcopyinfo(args->rpath, args->lpath, name, 1);
+        ci->next = *dirlist;
+        *dirlist = ci;
+    } else if (S_ISREG(mode) || S_ISLNK(mode)) {
+        copyinfo **filelist = args->filelist;
+
+        ci = mkcopyinfo(args->rpath, args->lpath, name, 0);
+        ci->time = time;
+        ci->mode = mode;
+        ci->size = size;
+        ci->next = *filelist;
+        *filelist = ci;
+    } else {
+        fprintf(stderr, "skipping special file '%s'\n", name);
+    }
+}
+
+static int remote_build_list(int syncfd, copyinfo **filelist,
+                             const char *rpath, const char *lpath)
+{
+    copyinfo *dirlist = NULL;
+    sync_ls_build_list_cb_args args;
+
+    args.filelist = filelist;
+    args.dirlist = &dirlist;
+    args.rpath = rpath;
+    args.lpath = lpath;
+
+    /* Put the files/dirs in rpath on the lists. */
+    if (sync_ls(syncfd, rpath, sync_ls_build_list_cb, (void *)&args)) {
+        return 1;
+    }
+
+    /* Recurse into each directory we found. */
+    while (dirlist != NULL) {
+        copyinfo *next = dirlist->next;
+        if (remote_build_list(syncfd, filelist, dirlist->src, dirlist->dst)) {
+            return 1;
+        }
+        free(dirlist);
+        dirlist = next;
+    }
+
+    return 0;
+}
+
+static int set_time_and_mode(const char *lpath, unsigned int time, unsigned int mode)
+{
+    struct utimbuf times = { time, time };
+    int r1 = utime(lpath, &times);
+
+    /* use umask for permissions */
+    mode_t mask=umask(0000);
+    umask(mask);
+    int r2 = chmod(lpath, mode & ~mask);
+
+    return r1 ? : r2;
+}
+
+static int copy_remote_dir_local(int fd, const char *rpath, const char *lpath,
+                                 int copy_attrs)
+{
+    copyinfo *filelist = 0;
+    copyinfo *ci, *next;
+    int pulled = 0;
+    int skipped = 0;
+
+    /* Make sure that both directory paths end in a slash. */
+    if (rpath[0] == 0 || lpath[0] == 0) return -1;
+    if (rpath[strlen(rpath) - 1] != '/') {
+        int  tmplen = strlen(rpath) + 2;
+        char *tmp = malloc(tmplen);
+        if (tmp == 0) return -1;
+        snprintf(tmp, tmplen, "%s/", rpath);
+        rpath = tmp;
+    }
+    if (lpath[strlen(lpath) - 1] != '/') {
+        int  tmplen = strlen(lpath) + 2;
+        char *tmp = malloc(tmplen);
+        if (tmp == 0) return -1;
+        snprintf(tmp, tmplen, "%s/", lpath);
+        lpath = tmp;
+    }
+
+    fprintf(stderr, "pull: building file list...\n");
+    /* Recursively build the list of files to copy. */
+    if (remote_build_list(fd, &filelist, rpath, lpath)) {
+        return -1;
+    }
+
+    for (ci = filelist; ci != 0; ci = next) {
+        next = ci->next;
+        if (ci->flag == 0) {
+            fprintf(stderr, "pull: %s -> %s\n", ci->src, ci->dst);
+            if (sync_recv(fd, ci->src, ci->dst, 0 /* no show progress */)) {
+                return 1;
+            }
+
+            if (copy_attrs && set_time_and_mode(ci->dst, ci->time, ci->mode)) {
+               return 1;
+            }
+            pulled++;
+        } else {
+            skipped++;
+        }
+        free(ci);
+    }
+
+    fprintf(stderr, "%d file%s pulled. %d file%s skipped.\n",
+            pulled, (pulled == 1) ? "" : "s",
+            skipped, (skipped == 1) ? "" : "s");
+
+    return 0;
+}
+
+int do_sync_pull(const char *rpath, const char *lpath, int show_progress, int copy_attrs)
+{
+    unsigned mode, time;
+    struct stat st;
+
+    int fd;
+
+    fd = adb_connect("sync:");
+    if(fd < 0) {
+        fprintf(stderr,"error: %s\n", adb_error());
+        return 1;
+    }
+
+    if(sync_readtime(fd, rpath, &time, &mode)) {
+        return 1;
+    }
+    if(mode == 0) {
+        fprintf(stderr,"remote object '%s' does not exist\n", rpath);
+        return 1;
+    }
+
+    if(S_ISREG(mode) || S_ISLNK(mode) || S_ISCHR(mode) || S_ISBLK(mode)) {
+        if(stat(lpath, &st) == 0) {
+            if(S_ISDIR(st.st_mode)) {
+                    /* if we're copying a remote file to a local directory,
+                    ** we *really* want to copy to localdir + "/" + remotefilename
+                    */
+                const char *name = adb_dirstop(rpath);
+                if(name == 0) {
+                    name = rpath;
+                } else {
+                    name++;
+                }
+                int  tmplen = strlen(name) + strlen(lpath) + 2;
+                char *tmp = malloc(tmplen);
+                if(tmp == 0) return 1;
+                snprintf(tmp, tmplen, "%s/%s", lpath, name);
+                lpath = tmp;
+            }
+        }
+        BEGIN();
+        if (sync_recv(fd, rpath, lpath, show_progress)) {
+            return 1;
+        } else {
+            if (copy_attrs && set_time_and_mode(lpath, time, mode))
+                return 1;
+            END();
+            sync_quit(fd);
+            return 0;
+        }
+    } else if(S_ISDIR(mode)) {
+        BEGIN();
+        if (copy_remote_dir_local(fd, rpath, lpath, copy_attrs)) {
+            return 1;
+        } else {
+            END();
+            sync_quit(fd);
+            return 0;
+        }
+    } else {
+        fprintf(stderr,"remote object '%s' not a file or directory\n", rpath);
+        return 1;
+    }
+}
+
+int do_sync_sync(const char *lpath, const char *rpath, int listonly)
+{
+    fprintf(stderr,"syncing %s...\n",rpath);
+
+    int fd = adb_connect("sync:");
+    if(fd < 0) {
+        fprintf(stderr,"error: %s\n", adb_error());
+        return 1;
+    }
+
+    BEGIN();
+    if(copy_local_dir_remote(fd, lpath, rpath, 1, listonly)){
+        return 1;
+    } else {
+        END();
+        sync_quit(fd);
+        return 0;
+    }
+}
diff --git a/package/utils/adbd/src/adb/file_sync_service.c b/package/utils/adbd/src/adb/file_sync_service.c
new file mode 100644
index 0000000..436ec02
--- /dev/null
+++ b/package/utils/adbd/src/adb/file_sync_service.c
@@ -0,0 +1,476 @@
+/*
+ * 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 <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <utime.h>
+#include <unistd.h>
+
+#include <errno.h>
+#include <private/android_filesystem_config.h>
+//#include <selinux/android.h> //changed by feilv
+#include "sysdeps.h"
+
+#define TRACE_TAG  TRACE_SYNC
+#include "adb.h"
+#include "file_sync_service.h"
+
+/* TODO: use fs_config to configure permissions on /data */
+static bool is_on_system(const char *name) {
+    const char *SYSTEM = "/system/";
+    return (strncmp(SYSTEM, name, strlen(SYSTEM)) == 0);
+}
+
+static int mkdirs(char *name)
+{
+    int ret;
+    char *x = name + 1;
+    uid_t uid = -1;
+    gid_t gid = -1;
+    unsigned int mode = 0775;
+    uint64_t cap = 0;
+
+    if(name[0] != '/') return -1;
+
+    for(;;) {
+        x = adb_dirstart(x);
+        if(x == 0) return 0;
+        *x = 0;
+        if (is_on_system(name)) {
+            fs_config(name, 1, &uid, &gid, &mode, &cap);
+        }
+        ret = adb_mkdir(name, mode);
+        if((ret < 0) && (errno != EEXIST)) {
+            D("mkdir(\"%s\") -> %s\n", name, strerror(errno));
+            *x = '/';
+            return ret;
+        } else if(ret == 0) {
+            ret = chown(name, uid, gid);
+            if (ret < 0) {
+                *x = '/';
+                return ret;
+            }
+            //selinux_android_restorecon(name, 0);
+        }
+        *x++ = '/';
+    }
+    return 0;
+}
+
+static int do_stat(int s, const char *path)
+{
+    syncmsg msg;
+    struct stat st;
+
+    msg.stat.id = ID_STAT;
+
+    if(lstat(path, &st)) {
+        msg.stat.mode = 0;
+        msg.stat.size = 0;
+        msg.stat.time = 0;
+    } else {
+        msg.stat.mode = htoll(st.st_mode);
+        msg.stat.size = htoll(st.st_size);
+        msg.stat.time = htoll(st.st_mtime);
+    }
+
+    return writex(s, &msg.stat, sizeof(msg.stat));
+}
+
+static int do_list(int s, const char *path)
+{
+    DIR *d;
+    struct dirent *de;
+    struct stat st;
+    syncmsg msg;
+    int len;
+
+    char tmp[1024 + 256 + 1];
+    char *fname;
+
+    len = strlen(path);
+    memcpy(tmp, path, len);
+    tmp[len] = '/';
+    fname = tmp + len + 1;
+
+    msg.dent.id = ID_DENT;
+
+    d = opendir(path);
+    if(d == 0) goto done;
+
+    while((de = readdir(d))) {
+        int len = strlen(de->d_name);
+
+            /* not supposed to be possible, but
+               if it does happen, let's not buffer overrun */
+        if(len > 256) continue;
+
+        strcpy(fname, de->d_name);
+        if(lstat(tmp, &st) == 0) {
+            msg.dent.mode = htoll(st.st_mode);
+            msg.dent.size = htoll(st.st_size);
+            msg.dent.time = htoll(st.st_mtime);
+            msg.dent.namelen = htoll(len);
+
+            if(writex(s, &msg.dent, sizeof(msg.dent)) ||
+               writex(s, de->d_name, len)) {
+                closedir(d);
+                return -1;
+            }
+        }
+    }
+
+    closedir(d);
+
+done:
+    msg.dent.id = ID_DONE;
+    msg.dent.mode = 0;
+    msg.dent.size = 0;
+    msg.dent.time = 0;
+    msg.dent.namelen = 0;
+    return writex(s, &msg.dent, sizeof(msg.dent));
+}
+
+static int fail_message(int s, const char *reason)
+{
+    syncmsg msg;
+    int len = strlen(reason);
+
+    D("sync: failure: %s\n", reason);
+
+    msg.data.id = ID_FAIL;
+    msg.data.size = htoll(len);
+    if(writex(s, &msg.data, sizeof(msg.data)) ||
+       writex(s, reason, len)) {
+        return -1;
+    } else {
+        return 0;
+    }
+}
+
+static int fail_errno(int s)
+{
+    return fail_message(s, strerror(errno));
+}
+
+static int handle_send_file(int s, char *path, uid_t uid,
+        gid_t gid, mode_t mode, char *buffer, bool do_unlink)
+{
+    syncmsg msg;
+    unsigned int timestamp = 0;
+    int fd;
+
+    fd = adb_open_mode(path, O_WRONLY | O_CREAT | O_EXCL, mode);
+    if(fd < 0 && errno == ENOENT) {
+        if(mkdirs(path) != 0) {
+            if(fail_errno(s))
+                return -1;
+            fd = -1;
+        } else {
+            fd = adb_open_mode(path, O_WRONLY | O_CREAT | O_EXCL, mode);
+        }
+    }
+    if(fd < 0 && errno == EEXIST) {
+        fd = adb_open_mode(path, O_WRONLY, mode);
+    }
+    if(fd < 0) {
+        if(fail_errno(s))
+            return -1;
+        fd = -1;
+    } else {
+        if(fchown(fd, uid, gid) != 0) {
+            fail_errno(s);
+            errno = 0;
+        }
+
+        /*
+         * fchown clears the setuid bit - restore it if present.
+         * Ignore the result of calling fchmod. It's not supported
+         * by all filesystems. b/12441485
+         */
+        fchmod(fd, mode);
+    }
+
+    for(;;) {
+        unsigned int len;
+
+        if(readx(s, &msg.data, sizeof(msg.data)))
+            goto fail;
+
+        if(msg.data.id != ID_DATA) {
+            if(msg.data.id == ID_DONE) {
+                timestamp = ltohl(msg.data.size);
+                break;
+            }
+            fail_message(s, "invalid data message");
+            goto fail;
+        }
+        len = ltohl(msg.data.size);
+        if(len > SYNC_DATA_MAX) {
+            fail_message(s, "oversize data message");
+            goto fail;
+        }
+        if(readx(s, buffer, len))
+            goto fail;
+
+        if(fd < 0)
+            continue;
+        if(writex(fd, buffer, len)) {
+            int saved_errno = errno;
+            adb_close(fd);
+            if (do_unlink) adb_unlink(path);
+            fd = -1;
+            errno = saved_errno;
+            if(fail_errno(s)) return -1;
+        }
+    }
+
+    if(fd >= 0) {
+        struct utimbuf u;
+        adb_close(fd);
+        //selinux_android_restorecon(path, 0);
+        u.actime = timestamp;
+        u.modtime = timestamp;
+        utime(path, &u);
+
+        msg.status.id = ID_OKAY;
+        msg.status.msglen = 0;
+        if(writex(s, &msg.status, sizeof(msg.status)))
+            return -1;
+    }
+    return 0;
+
+fail:
+    if(fd >= 0)
+        adb_close(fd);
+    if (do_unlink) adb_unlink(path);
+    return -1;
+}
+
+#ifdef HAVE_SYMLINKS
+static int handle_send_link(int s, char *path, char *buffer)
+{
+    syncmsg msg;
+    unsigned int len;
+    int ret;
+
+    if(readx(s, &msg.data, sizeof(msg.data)))
+        return -1;
+
+    if(msg.data.id != ID_DATA) {
+        fail_message(s, "invalid data message: expected ID_DATA");
+        return -1;
+    }
+
+    len = ltohl(msg.data.size);
+    if(len > SYNC_DATA_MAX) {
+        fail_message(s, "oversize data message");
+        return -1;
+    }
+    if(readx(s, buffer, len))
+        return -1;
+
+    ret = symlink(buffer, path);
+    if(ret && errno == ENOENT) {
+        if(mkdirs(path) != 0) {
+            fail_errno(s);
+            return -1;
+        }
+        ret = symlink(buffer, path);
+    }
+    if(ret) {
+        fail_errno(s);
+        return -1;
+    }
+
+    if(readx(s, &msg.data, sizeof(msg.data)))
+        return -1;
+
+    if(msg.data.id == ID_DONE) {
+        msg.status.id = ID_OKAY;
+        msg.status.msglen = 0;
+        if(writex(s, &msg.status, sizeof(msg.status)))
+            return -1;
+    } else {
+        fail_message(s, "invalid data message: expected ID_DONE");
+        return -1;
+    }
+
+    return 0;
+}
+#endif /* HAVE_SYMLINKS */
+
+static int do_send(int s, char *path, char *buffer)
+{
+    char *tmp;
+    unsigned int mode;
+    int is_link, ret;
+    bool do_unlink;
+
+    tmp = strrchr(path,',');
+    if(tmp) {
+        *tmp = 0;
+        errno = 0;
+        mode = strtoul(tmp + 1, NULL, 0);
+#ifndef HAVE_SYMLINKS
+        is_link = 0;
+#else
+        is_link = S_ISLNK((mode_t) mode);
+#endif
+        mode &= 0777;
+    }
+    if(!tmp || errno) {
+        mode = 0644;
+        is_link = 0;
+        do_unlink = true;
+    } else {
+        struct stat st;
+        /* Don't delete files before copying if they are not "regular" */
+        do_unlink = lstat(path, &st) || S_ISREG(st.st_mode) || S_ISLNK(st.st_mode);
+        if (do_unlink) {
+            adb_unlink(path);
+        }
+    }
+
+#ifdef HAVE_SYMLINKS
+    if(is_link)
+        ret = handle_send_link(s, path, buffer);
+    else {
+#else
+    { (void)is_link;
+#endif
+        uid_t uid = -1;
+        gid_t gid = -1;
+        uint64_t cap = 0;
+
+        /* copy user permission bits to "group" and "other" permissions */
+        mode |= ((mode >> 3) & 0070);
+        mode |= ((mode >> 3) & 0007);
+
+        tmp = path;
+        if(*tmp == '/') {
+            tmp++;
+        }
+        if (is_on_system(path)) {
+            fs_config(tmp, 0, &uid, &gid, &mode, &cap);
+        }
+        ret = handle_send_file(s, path, uid, gid, mode, buffer, do_unlink);
+    }
+
+    return ret;
+}
+
+static int do_recv(int s, const char *path, char *buffer)
+{
+    syncmsg msg;
+    int fd, r;
+
+    fd = adb_open(path, O_RDONLY);
+    if(fd < 0) {
+        if(fail_errno(s)) return -1;
+        return 0;
+    }
+
+    msg.data.id = ID_DATA;
+    for(;;) {
+        r = adb_read(fd, buffer, SYNC_DATA_MAX);
+        if(r <= 0) {
+            if(r == 0) break;
+            if(errno == EINTR) continue;
+            r = fail_errno(s);
+            adb_close(fd);
+            return r;
+        }
+        msg.data.size = htoll(r);
+        if(writex(s, &msg.data, sizeof(msg.data)) ||
+           writex(s, buffer, r)) {
+            adb_close(fd);
+            return -1;
+        }
+    }
+
+    adb_close(fd);
+
+    msg.data.id = ID_DONE;
+    msg.data.size = 0;
+    if(writex(s, &msg.data, sizeof(msg.data))) {
+        return -1;
+    }
+
+    return 0;
+}
+
+void file_sync_service(int fd, void *cookie)
+{
+    syncmsg msg;
+    char name[1025];
+    unsigned namelen;
+
+    char *buffer = malloc(SYNC_DATA_MAX);
+    if(buffer == 0) goto fail;
+
+    for(;;) {
+        D("sync: waiting for command\n");
+
+        if(readx(fd, &msg.req, sizeof(msg.req))) {
+            fail_message(fd, "command read failure");
+            break;
+        }
+        namelen = ltohl(msg.req.namelen);
+        if(namelen > 1024) {
+            fail_message(fd, "invalid namelen");
+            break;
+        }
+        if(readx(fd, name, namelen)) {
+            fail_message(fd, "filename read failure");
+            break;
+        }
+        name[namelen] = 0;
+
+        msg.req.namelen = 0;
+        D("sync: '%s' '%s'\n", (char*) &msg.req, name);
+
+        switch(msg.req.id) {
+        case ID_STAT:
+            if(do_stat(fd, name)) goto fail;
+            break;
+        case ID_LIST:
+            if(do_list(fd, name)) goto fail;
+            break;
+        case ID_SEND:
+            if(do_send(fd, name, buffer)) goto fail;
+            break;
+        case ID_RECV:
+            if(do_recv(fd, name, buffer)) goto fail;
+            break;
+        case ID_QUIT:
+            goto fail;
+        default:
+            fail_message(fd, "unknown command");
+            goto fail;
+        }
+    }
+
+fail:
+    if(buffer != 0) free(buffer);
+    D("sync: done\n");
+    adb_close(fd);
+}
diff --git a/package/utils/adbd/src/adb/file_sync_service.h b/package/utils/adbd/src/adb/file_sync_service.h
new file mode 100644
index 0000000..8ea239e
--- /dev/null
+++ b/package/utils/adbd/src/adb/file_sync_service.h
@@ -0,0 +1,87 @@
+/*
+ * 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 _FILE_SYNC_SERVICE_H_
+#define _FILE_SYNC_SERVICE_H_
+
+#ifdef HAVE_BIG_ENDIAN
+static inline unsigned __swap_uint32(unsigned x) 
+{
+    return (((x) & 0xFF000000) >> 24)
+        | (((x) & 0x00FF0000) >> 8)
+        | (((x) & 0x0000FF00) << 8)
+        | (((x) & 0x000000FF) << 24);
+}
+#define htoll(x) __swap_uint32(x)
+#define ltohl(x) __swap_uint32(x)
+#define MKID(a,b,c,d) ((d) | ((c) << 8) | ((b) << 16) | ((a) << 24))
+#else
+#define htoll(x) (x)
+#define ltohl(x) (x)
+#define MKID(a,b,c,d) ((a) | ((b) << 8) | ((c) << 16) | ((d) << 24))
+#endif
+
+#define ID_STAT MKID('S','T','A','T')
+#define ID_LIST MKID('L','I','S','T')
+#define ID_ULNK MKID('U','L','N','K')
+#define ID_SEND MKID('S','E','N','D')
+#define ID_RECV MKID('R','E','C','V')
+#define ID_DENT MKID('D','E','N','T')
+#define ID_DONE MKID('D','O','N','E')
+#define ID_DATA MKID('D','A','T','A')
+#define ID_OKAY MKID('O','K','A','Y')
+#define ID_FAIL MKID('F','A','I','L')
+#define ID_QUIT MKID('Q','U','I','T')
+
+typedef union {
+    unsigned id;
+    struct {
+        unsigned id;
+        unsigned namelen;
+    } req;
+    struct {
+        unsigned id;
+        unsigned mode;
+        unsigned size;
+        unsigned time;
+    } stat;
+    struct {
+        unsigned id;
+        unsigned mode;
+        unsigned size;
+        unsigned time;
+        unsigned namelen;
+    } dent;
+    struct {
+        unsigned id;
+        unsigned size;
+    } data;
+    struct {
+        unsigned id;
+        unsigned msglen;
+    } status;
+} syncmsg;
+
+
+void file_sync_service(int fd, void *cookie);
+int do_sync_ls(const char *path);
+int do_sync_push(const char *lpath, const char *rpath, int verifyApk, int show_progress);
+int do_sync_sync(const char *lpath, const char *rpath, int listonly);
+int do_sync_pull(const char *rpath, const char *lpath, int show_progress, int pullTime);
+
+#define SYNC_DATA_MAX (64*1024)
+
+#endif
diff --git a/package/utils/adbd/src/adb/framebuffer_service.c b/package/utils/adbd/src/adb/framebuffer_service.c
new file mode 100644
index 0000000..906dc95
--- /dev/null
+++ b/package/utils/adbd/src/adb/framebuffer_service.c
@@ -0,0 +1,192 @@
+/*
+ * 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 <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include "fdevent.h"
+#include "adb.h"
+
+#include <linux/fb.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+
+#ifndef TEMP_FAILURE_RETRY
+/* Used to retry syscalls that can return EINTR. */
+#define TEMP_FAILURE_RETRY(exp) ({         \
+    typeof (exp) _rc;                      \
+    do {                                   \
+        _rc = (exp);                       \
+    } while (_rc == -1 && errno == EINTR); \
+    _rc; })
+#endif
+
+/* TODO:
+** - sync with vsync to avoid tearing
+*/
+/* This version number defines the format of the fbinfo struct.
+   It must match versioning in ddms where this data is consumed. */
+#define DDMS_RAWIMAGE_VERSION 1
+struct fbinfo {
+    unsigned int version;
+    unsigned int bpp;
+    unsigned int size;
+    unsigned int width;
+    unsigned int height;
+    unsigned int red_offset;
+    unsigned int red_length;
+    unsigned int blue_offset;
+    unsigned int blue_length;
+    unsigned int green_offset;
+    unsigned int green_length;
+    unsigned int alpha_offset;
+    unsigned int alpha_length;
+} __attribute__((packed));
+
+void framebuffer_service(int fd, void *cookie)
+{
+    struct fbinfo fbinfo;
+    unsigned int i, bsize;
+    char buf[640];
+    int fd_screencap;
+    int w, h, f;
+    int fds[2];
+
+    if (pipe2(fds, O_CLOEXEC) < 0) goto pipefail;
+
+    pid_t pid = fork();
+    if (pid < 0) goto done;
+
+    if (pid == 0) {
+        dup2(fds[1], STDOUT_FILENO);
+        close(fds[0]);
+        close(fds[1]);
+        const char* command = "screencap";
+        const char *args[2] = {command, NULL};
+        execvp(command, (char**)args);
+        exit(1);
+    }
+
+    fd_screencap = fds[0];
+
+    /* read w, h & format */
+    if(readx(fd_screencap, &w, 4)) goto done;
+    if(readx(fd_screencap, &h, 4)) goto done;
+    if(readx(fd_screencap, &f, 4)) goto done;
+
+    fbinfo.version = DDMS_RAWIMAGE_VERSION;
+    /* see hardware/hardware.h */
+    switch (f) {
+        case 1: /* RGBA_8888 */
+            fbinfo.bpp = 32;
+            fbinfo.size = w * h * 4;
+            fbinfo.width = w;
+            fbinfo.height = h;
+            fbinfo.red_offset = 0;
+            fbinfo.red_length = 8;
+            fbinfo.green_offset = 8;
+            fbinfo.green_length = 8;
+            fbinfo.blue_offset = 16;
+            fbinfo.blue_length = 8;
+            fbinfo.alpha_offset = 24;
+            fbinfo.alpha_length = 8;
+            break;
+        case 2: /* RGBX_8888 */
+            fbinfo.bpp = 32;
+            fbinfo.size = w * h * 4;
+            fbinfo.width = w;
+            fbinfo.height = h;
+            fbinfo.red_offset = 0;
+            fbinfo.red_length = 8;
+            fbinfo.green_offset = 8;
+            fbinfo.green_length = 8;
+            fbinfo.blue_offset = 16;
+            fbinfo.blue_length = 8;
+            fbinfo.alpha_offset = 24;
+            fbinfo.alpha_length = 0;
+            break;
+        case 3: /* RGB_888 */
+            fbinfo.bpp = 24;
+            fbinfo.size = w * h * 3;
+            fbinfo.width = w;
+            fbinfo.height = h;
+            fbinfo.red_offset = 0;
+            fbinfo.red_length = 8;
+            fbinfo.green_offset = 8;
+            fbinfo.green_length = 8;
+            fbinfo.blue_offset = 16;
+            fbinfo.blue_length = 8;
+            fbinfo.alpha_offset = 24;
+            fbinfo.alpha_length = 0;
+            break;
+        case 4: /* RGB_565 */
+            fbinfo.bpp = 16;
+            fbinfo.size = w * h * 2;
+            fbinfo.width = w;
+            fbinfo.height = h;
+            fbinfo.red_offset = 11;
+            fbinfo.red_length = 5;
+            fbinfo.green_offset = 5;
+            fbinfo.green_length = 6;
+            fbinfo.blue_offset = 0;
+            fbinfo.blue_length = 5;
+            fbinfo.alpha_offset = 0;
+            fbinfo.alpha_length = 0;
+            break;
+        case 5: /* BGRA_8888 */
+            fbinfo.bpp = 32;
+            fbinfo.size = w * h * 4;
+            fbinfo.width = w;
+            fbinfo.height = h;
+            fbinfo.red_offset = 16;
+            fbinfo.red_length = 8;
+            fbinfo.green_offset = 8;
+            fbinfo.green_length = 8;
+            fbinfo.blue_offset = 0;
+            fbinfo.blue_length = 8;
+            fbinfo.alpha_offset = 24;
+            fbinfo.alpha_length = 8;
+           break;
+        default:
+            goto done;
+    }
+
+    /* write header */
+    if(writex(fd, &fbinfo, sizeof(fbinfo))) goto done;
+
+    /* write data */
+    for(i = 0; i < fbinfo.size; i += bsize) {
+      bsize = sizeof(buf);
+      if (i + bsize > fbinfo.size)
+        bsize = fbinfo.size - i;
+      if(readx(fd_screencap, buf, bsize)) goto done;
+      if(writex(fd, buf, bsize)) goto done;
+    }
+
+done:
+    TEMP_FAILURE_RETRY(waitpid(pid, NULL, 0));
+
+    close(fds[0]);
+    close(fds[1]);
+pipefail:
+    close(fd);
+}
diff --git a/package/utils/adbd/src/adb/get_my_path_darwin.c b/package/utils/adbd/src/adb/get_my_path_darwin.c
new file mode 100644
index 0000000..5b95d15
--- /dev/null
+++ b/package/utils/adbd/src/adb/get_my_path_darwin.c
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ */
+
+#import <Carbon/Carbon.h>
+#include <unistd.h>
+
+void get_my_path(char *s, size_t maxLen)
+{
+    ProcessSerialNumber psn;
+    GetCurrentProcess(&psn);
+    CFDictionaryRef dict;
+    dict = ProcessInformationCopyDictionary(&psn, 0xffffffff);
+    CFStringRef value = (CFStringRef)CFDictionaryGetValue(dict,
+                CFSTR("CFBundleExecutable"));
+    CFStringGetCString(value, s, maxLen, kCFStringEncodingUTF8);
+}
+
diff --git a/package/utils/adbd/src/adb/get_my_path_freebsd.c b/package/utils/adbd/src/adb/get_my_path_freebsd.c
new file mode 100644
index 0000000..b06ec66
--- /dev/null
+++ b/package/utils/adbd/src/adb/get_my_path_freebsd.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2009 bsdroid project
+ *               Alexey Tarasov <tarasov@dodologics.com>
+ *
+ * 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 <sys/types.h>
+#include <unistd.h>
+#include <limits.h>
+#include <stdio.h>
+
+void
+get_my_path(char *exe, size_t maxLen)
+{
+    char proc[64];
+
+    snprintf(proc, sizeof(proc), "/proc/%d/file", getpid());
+
+    int err = readlink(proc, exe, maxLen - 1);
+
+    exe[err > 0 ? err : 0] = '\0';
+}
+
diff --git a/package/utils/adbd/src/adb/get_my_path_linux.c b/package/utils/adbd/src/adb/get_my_path_linux.c
new file mode 100644
index 0000000..179c3dd
--- /dev/null
+++ b/package/utils/adbd/src/adb/get_my_path_linux.c
@@ -0,0 +1,33 @@
+/*
+ * 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 <sys/types.h>
+#include <unistd.h>
+#include <limits.h>
+#include <stdio.h>
+
+void get_my_path(char *exe, size_t maxLen)
+{
+    char proc[64];
+    snprintf(proc, sizeof proc, "/proc/%d/exe", getpid());
+    int err = readlink(proc, exe, maxLen - 1);
+    if(err > 0) {
+        exe[err] = '\0';
+    } else {
+        exe[0] = '\0';
+    }
+}
+
diff --git a/package/utils/adbd/src/adb/get_my_path_windows.c b/package/utils/adbd/src/adb/get_my_path_windows.c
new file mode 100644
index 0000000..ddf2816
--- /dev/null
+++ b/package/utils/adbd/src/adb/get_my_path_windows.c
@@ -0,0 +1,34 @@
+/*
+ * 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 <limits.h>
+#include <assert.h>
+#include <windows.h>
+
+void get_my_path(char *exe, size_t maxLen)
+{
+    char  *r;
+
+    /* XXX: should be GetModuleFileNameA */
+    if (GetModuleFileName(NULL, exe, maxLen) > 0) {
+        r = strrchr(exe, '\\');
+        if (r != NULL)
+            *r = '\0';
+    } else {
+        exe[0] = '\0';
+    }
+}
+
diff --git a/package/utils/adbd/src/adb/jdwp_service.c b/package/utils/adbd/src/adb/jdwp_service.c
new file mode 100644
index 0000000..cd62b55
--- /dev/null
+++ b/package/utils/adbd/src/adb/jdwp_service.c
@@ -0,0 +1,735 @@
+/* implement the "debug-ports" and "track-debug-ports" device services */
+#include "sysdeps.h"
+#define  TRACE_TAG   TRACE_JDWP
+#include "adb.h"
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+/* here's how these things work.
+
+   when adbd starts, it creates a unix server socket
+   named @vm-debug-control (@ is a shortcut for "first byte is zero"
+   to use the private namespace instead of the file system)
+
+   when a new JDWP daemon thread starts in a new VM process, it creates
+   a connection to @vm-debug-control to announce its availability.
+
+
+     JDWP thread                             @vm-debug-control
+         |                                         |
+         |------------------------------->         |
+         | hello I'm in process <pid>              |
+         |                                         |
+         |                                         |
+
+    the connection is kept alive. it will be closed automatically if
+    the JDWP process terminates (this allows adbd to detect dead
+    processes).
+
+    adbd thus maintains a list of "active" JDWP processes. it can send
+    its content to clients through the "device:debug-ports" service,
+    or even updates through the "device:track-debug-ports" service.
+
+    when a debugger wants to connect, it simply runs the command
+    equivalent to  "adb forward tcp:<hostport> jdwp:<pid>"
+
+    "jdwp:<pid>" is a new forward destination format used to target
+    a given JDWP process on the device. when sutch a request arrives,
+    adbd does the following:
+
+      - first, it calls socketpair() to create a pair of equivalent
+        sockets.
+
+      - it attaches the first socket in the pair to a local socket
+        which is itself attached to the transport's remote socket:
+
+
+      - it sends the file descriptor of the second socket directly
+        to the JDWP process with the help of sendmsg()
+
+
+     JDWP thread                             @vm-debug-control
+         |                                         |
+         |                  <----------------------|
+         |           OK, try this file descriptor  |
+         |                                         |
+         |                                         |
+
+   then, the JDWP thread uses this new socket descriptor as its
+   pass-through connection to the debugger (and receives the
+   JDWP-Handshake message, answers to it, etc...)
+
+   this gives the following graphics:
+                    ____________________________________
+                   |                                    |
+                   |          ADB Server (host)         |
+                   |                                    |
+        Debugger <---> LocalSocket <----> RemoteSocket  |
+                   |                           ^^       |
+                   |___________________________||_______|
+                                               ||
+                                     Transport ||
+           (TCP for emulator - USB for device) ||
+                                               ||
+                    ___________________________||_______
+                   |                           ||       |
+                   |          ADBD  (device)   ||       |
+                   |                           VV       |
+         JDWP <======> LocalSocket <----> RemoteSocket  |
+                   |                                    |
+                   |____________________________________|
+
+    due to the way adb works, this doesn't need a special socket
+    type or fancy handling of socket termination if either the debugger
+    or the JDWP process closes the connection.
+
+    THIS IS THE SIMPLEST IMPLEMENTATION I COULD FIND, IF YOU HAPPEN
+    TO HAVE A BETTER IDEA, LET ME KNOW - Digit
+
+**********************************************************************/
+
+/** JDWP PID List Support Code
+ ** for each JDWP process, we record its pid and its connected socket
+ **/
+
+#define  MAX_OUT_FDS   4
+
+#if !ADB_HOST
+
+#include <sys/socket.h>
+#include <sys/un.h>
+
+typedef struct JdwpProcess  JdwpProcess;
+struct JdwpProcess {
+    JdwpProcess*  next;
+    JdwpProcess*  prev;
+    int           pid;
+    int           socket;
+    fdevent*      fde;
+
+    char          in_buff[4];  /* input character to read PID */
+    int           in_len;      /* number from JDWP process    */
+
+    int           out_fds[MAX_OUT_FDS]; /* output array of file descriptors */
+    int           out_count;            /* to send to the JDWP process      */
+};
+
+static JdwpProcess  _jdwp_list;
+
+static int
+jdwp_process_list( char*  buffer, int  bufferlen )
+{
+    char*         end  = buffer + bufferlen;
+    char*         p    = buffer;
+    JdwpProcess*  proc = _jdwp_list.next;
+
+    for ( ; proc != &_jdwp_list; proc = proc->next ) {
+        int  len;
+
+        /* skip transient connections */
+        if (proc->pid < 0)
+            continue;
+
+        len = snprintf(p, end-p, "%d\n", proc->pid);
+        if (p + len >= end)
+            break;
+        p += len;
+    }
+    p[0] = 0;
+    return (p - buffer);
+}
+
+
+static int
+jdwp_process_list_msg( char*  buffer, int  bufferlen )
+{
+    char  head[5];
+    int   len = jdwp_process_list( buffer+4, bufferlen-4 );
+    snprintf(head, sizeof head, "%04x", len);
+    memcpy(buffer, head, 4);
+    return len + 4;
+}
+
+
+static void  jdwp_process_list_updated(void);
+
+static void
+jdwp_process_free( JdwpProcess*  proc )
+{
+    if (proc) {
+        int  n;
+
+        proc->prev->next = proc->next;
+        proc->next->prev = proc->prev;
+
+        if (proc->socket >= 0) {
+            adb_shutdown(proc->socket);
+            adb_close(proc->socket);
+            proc->socket = -1;
+        }
+
+        if (proc->fde != NULL) {
+            fdevent_destroy(proc->fde);
+            proc->fde = NULL;
+        }
+        proc->pid = -1;
+
+        for (n = 0; n < proc->out_count; n++) {
+            adb_close(proc->out_fds[n]);
+        }
+        proc->out_count = 0;
+
+        free(proc);
+
+        jdwp_process_list_updated();
+    }
+}
+
+
+static void  jdwp_process_event(int, unsigned, void*);  /* forward */
+
+
+static JdwpProcess*
+jdwp_process_alloc( int  socket )
+{
+    JdwpProcess*  proc = calloc(1,sizeof(*proc));
+
+    if (proc == NULL) {
+        D("not enough memory to create new JDWP process\n");
+        return NULL;
+    }
+
+    proc->socket = socket;
+    proc->pid    = -1;
+    proc->next   = proc;
+    proc->prev   = proc;
+
+    proc->fde = fdevent_create( socket, jdwp_process_event, proc );
+    if (proc->fde == NULL) {
+        D("could not create fdevent for new JDWP process\n" );
+        free(proc);
+        return NULL;
+    }
+
+    proc->fde->state |= FDE_DONT_CLOSE;
+    proc->in_len      = 0;
+    proc->out_count   = 0;
+
+    /* append to list */
+    proc->next = &_jdwp_list;
+    proc->prev = proc->next->prev;
+
+    proc->prev->next = proc;
+    proc->next->prev = proc;
+
+    /* start by waiting for the PID */
+    fdevent_add(proc->fde, FDE_READ);
+
+    return proc;
+}
+
+
+static void
+jdwp_process_event( int  socket, unsigned  events, void*  _proc )
+{
+    JdwpProcess*  proc = _proc;
+
+    if (events & FDE_READ) {
+        if (proc->pid < 0) {
+            /* read the PID as a 4-hexchar string */
+            char*  p    = proc->in_buff + proc->in_len;
+            int    size = 4 - proc->in_len;
+            char   temp[5];
+            while (size > 0) {
+                int  len = recv( socket, p, size, 0 );
+                if (len < 0) {
+                    if (errno == EINTR)
+                        continue;
+                    if (errno == EAGAIN)
+                        return;
+                    /* this can fail here if the JDWP process crashes very fast */
+                    D("weird unknown JDWP process failure: %s\n",
+                      strerror(errno));
+
+                    goto CloseProcess;
+                }
+                if (len == 0) {  /* end of stream ? */
+                    D("weird end-of-stream from unknown JDWP process\n");
+                    goto CloseProcess;
+                }
+                p            += len;
+                proc->in_len += len;
+                size         -= len;
+            }
+            /* we have read 4 characters, now decode the pid */
+            memcpy(temp, proc->in_buff, 4);
+            temp[4] = 0;
+
+            if (sscanf( temp, "%04x", &proc->pid ) != 1) {
+                D("could not decode JDWP %p PID number: '%s'\n", proc, temp);
+                goto CloseProcess;
+            }
+
+            /* all is well, keep reading to detect connection closure */
+            D("Adding pid %d to jdwp process list\n", proc->pid);
+            jdwp_process_list_updated();
+        }
+        else
+        {
+            /* the pid was read, if we get there it's probably because the connection
+             * was closed (e.g. the JDWP process exited or crashed) */
+            char  buf[32];
+
+            for (;;) {
+                int  len = recv(socket, buf, sizeof(buf), 0);
+
+                if (len <= 0) {
+                    if (len < 0 && errno == EINTR)
+                        continue;
+                    if (len < 0 && errno == EAGAIN)
+                        return;
+                    else {
+                        D("terminating JDWP %d connection: %s\n", proc->pid,
+                          strerror(errno));
+                        break;
+                    }
+                }
+                else {
+                    D( "ignoring unexpected JDWP %d control socket activity (%d bytes)\n",
+                       proc->pid, len );
+                }
+            }
+
+        CloseProcess:
+            if (proc->pid >= 0)
+                D( "remove pid %d to jdwp process list\n", proc->pid );
+            jdwp_process_free(proc);
+            return;
+        }
+    }
+
+    if (events & FDE_WRITE) {
+        D("trying to write to JDWP pid controli (count=%d first=%d) %d\n",
+          proc->pid, proc->out_count, proc->out_fds[0]);
+        if (proc->out_count > 0) {
+            int  fd = proc->out_fds[0];
+            int  n, ret;
+            struct cmsghdr*  cmsg;
+            struct msghdr    msg;
+            struct iovec     iov;
+            char             dummy = '!';
+            char             buffer[sizeof(struct cmsghdr) + sizeof(int)];
+            int flags;
+
+            iov.iov_base       = &dummy;
+            iov.iov_len        = 1;
+            msg.msg_name       = NULL;
+            msg.msg_namelen    = 0;
+            msg.msg_iov        = &iov;
+            msg.msg_iovlen     = 1;
+            msg.msg_flags      = 0;
+            msg.msg_control    = buffer;
+            msg.msg_controllen = sizeof(buffer);
+
+            cmsg = CMSG_FIRSTHDR(&msg);
+            cmsg->cmsg_len   = msg.msg_controllen;
+            cmsg->cmsg_level = SOL_SOCKET;
+            cmsg->cmsg_type  = SCM_RIGHTS;
+            ((int*)CMSG_DATA(cmsg))[0] = fd;
+
+            flags = fcntl(proc->socket,F_GETFL,0);
+
+            if (flags == -1) {
+                D("failed to get cntl flags for socket %d: %s\n",
+                  proc->pid, strerror(errno));
+                goto CloseProcess;
+
+            }
+
+            if (fcntl(proc->socket, F_SETFL, flags & ~O_NONBLOCK) == -1) {
+                D("failed to remove O_NONBLOCK flag for socket %d: %s\n",
+                  proc->pid, strerror(errno));
+                goto CloseProcess;
+            }
+
+            for (;;) {
+                ret = sendmsg(proc->socket, &msg, 0);
+                if (ret >= 0) {
+                    adb_close(fd);
+                    break;
+                }
+                if (errno == EINTR)
+                    continue;
+                D("sending new file descriptor to JDWP %d failed: %s\n",
+                  proc->pid, strerror(errno));
+                goto CloseProcess;
+            }
+
+            D("sent file descriptor %d to JDWP process %d\n",
+              fd, proc->pid);
+
+            for (n = 1; n < proc->out_count; n++)
+                proc->out_fds[n-1] = proc->out_fds[n];
+
+            if (fcntl(proc->socket, F_SETFL, flags) == -1) {
+                D("failed to set O_NONBLOCK flag for socket %d: %s\n",
+                  proc->pid, strerror(errno));
+                goto CloseProcess;
+            }
+
+            if (--proc->out_count == 0)
+                fdevent_del( proc->fde, FDE_WRITE );
+        }
+    }
+}
+
+
+int
+create_jdwp_connection_fd(int  pid)
+{
+    JdwpProcess*  proc = _jdwp_list.next;
+
+    D("looking for pid %d in JDWP process list\n", pid);
+    for ( ; proc != &_jdwp_list; proc = proc->next ) {
+        if (proc->pid == pid) {
+            goto FoundIt;
+        }
+    }
+    D("search failed !!\n");
+    return -1;
+
+FoundIt:
+    {
+        int  fds[2];
+
+        if (proc->out_count >= MAX_OUT_FDS) {
+            D("%s: too many pending JDWP connection for pid %d\n",
+              __FUNCTION__, pid);
+            return -1;
+        }
+
+        if (adb_socketpair(fds) < 0) {
+            D("%s: socket pair creation failed: %s\n",
+              __FUNCTION__, strerror(errno));
+            return -1;
+        }
+
+        proc->out_fds[ proc->out_count ] = fds[1];
+        if (++proc->out_count == 1)
+            fdevent_add( proc->fde, FDE_WRITE );
+
+        return fds[0];
+    }
+}
+
+/**  VM DEBUG CONTROL SOCKET
+ **
+ **  we do implement a custom asocket to receive the data
+ **/
+
+/* name of the debug control Unix socket */
+#define  JDWP_CONTROL_NAME      "\0jdwp-control"
+#define  JDWP_CONTROL_NAME_LEN  (sizeof(JDWP_CONTROL_NAME)-1)
+
+typedef struct {
+    int       listen_socket;
+    fdevent*  fde;
+
+} JdwpControl;
+
+
+static void
+jdwp_control_event(int  s, unsigned events, void*  user);
+
+
+static int
+jdwp_control_init( JdwpControl*  control,
+                   const char*   sockname,
+                   int           socknamelen )
+{
+    struct sockaddr_un   addr;
+    socklen_t            addrlen;
+    int                  s;
+    int                  maxpath = sizeof(addr.sun_path);
+    int                  pathlen = socknamelen;
+
+    if (pathlen >= maxpath) {
+        D( "vm debug control socket name too long (%d extra chars)\n",
+           pathlen+1-maxpath );
+        return -1;
+    }
+
+    memset(&addr, 0, sizeof(addr));
+    addr.sun_family = AF_UNIX;
+    memcpy(addr.sun_path, sockname, socknamelen);
+
+    s = socket( AF_UNIX, SOCK_STREAM, 0 );
+    if (s < 0) {
+        D( "could not create vm debug control socket. %d: %s\n",
+           errno, strerror(errno));
+        return -1;
+    }
+
+    addrlen = (pathlen + sizeof(addr.sun_family));
+
+    if (bind(s, (struct sockaddr*)&addr, addrlen) < 0) {
+        D( "could not bind vm debug control socket: %d: %s\n",
+           errno, strerror(errno) );
+        adb_close(s);
+        return -1;
+    }
+
+    if ( listen(s, 4) < 0 ) {
+        D("listen failed in jdwp control socket: %d: %s\n",
+          errno, strerror(errno));
+        adb_close(s);
+        return -1;
+    }
+
+    control->listen_socket = s;
+
+    control->fde = fdevent_create(s, jdwp_control_event, control);
+    if (control->fde == NULL) {
+        D( "could not create fdevent for jdwp control socket\n" );
+        adb_close(s);
+        return -1;
+    }
+
+    /* only wait for incoming connections */
+    fdevent_add(control->fde, FDE_READ);
+    close_on_exec(s);
+
+    D("jdwp control socket started (%d)\n", control->listen_socket);
+    return 0;
+}
+
+
+static void
+jdwp_control_event( int  s, unsigned  events, void*  _control )
+{
+    JdwpControl*  control = (JdwpControl*) _control;
+
+    if (events & FDE_READ) {
+        struct sockaddr   addr;
+        socklen_t         addrlen = sizeof(addr);
+        int               s = -1;
+        JdwpProcess*      proc;
+
+        do {
+            s = adb_socket_accept( control->listen_socket, &addr, &addrlen );
+            if (s < 0) {
+                if (errno == EINTR)
+                    continue;
+                if (errno == ECONNABORTED) {
+                    /* oops, the JDWP process died really quick */
+                    D("oops, the JDWP process died really quick\n");
+                    return;
+                }
+                /* the socket is probably closed ? */
+                D( "weird accept() failed on jdwp control socket: %s\n",
+                   strerror(errno) );
+                return;
+            }
+        }
+        while (s < 0);
+
+        proc = jdwp_process_alloc( s );
+        if (proc == NULL)
+            return;
+    }
+}
+
+
+static JdwpControl   _jdwp_control;
+
+/** "jdwp" local service implementation
+ ** this simply returns the list of known JDWP process pids
+ **/
+
+typedef struct {
+    asocket  socket;
+    int      pass;
+} JdwpSocket;
+
+static void
+jdwp_socket_close( asocket*  s )
+{
+    asocket*  peer = s->peer;
+
+    remove_socket(s);
+
+    if (peer) {
+        peer->peer = NULL;
+        peer->close(peer);
+    }
+    free(s);
+}
+
+static int
+jdwp_socket_enqueue( asocket*  s, apacket*  p )
+{
+    /* you can't write to this asocket */
+    put_apacket(p);
+    s->peer->close(s->peer);
+    return -1;
+}
+
+
+static void
+jdwp_socket_ready( asocket*  s )
+{
+    JdwpSocket*  jdwp = (JdwpSocket*)s;
+    asocket*     peer = jdwp->socket.peer;
+
+   /* on the first call, send the list of pids,
+    * on the second one, close the connection
+    */
+    if (jdwp->pass == 0) {
+        apacket*  p = get_apacket();
+        p->len = jdwp_process_list((char*)p->data, MAX_PAYLOAD);
+        peer->enqueue(peer, p);
+        jdwp->pass = 1;
+    }
+    else {
+        peer->close(peer);
+    }
+}
+
+asocket*
+create_jdwp_service_socket( void )
+{
+    JdwpSocket*  s = calloc(sizeof(*s),1);
+
+    if (s == NULL)
+        return NULL;
+
+    install_local_socket(&s->socket);
+
+    s->socket.ready   = jdwp_socket_ready;
+    s->socket.enqueue = jdwp_socket_enqueue;
+    s->socket.close   = jdwp_socket_close;
+    s->pass           = 0;
+
+    return &s->socket;
+}
+
+/** "track-jdwp" local service implementation
+ ** this periodically sends the list of known JDWP process pids
+ ** to the client...
+ **/
+
+typedef struct JdwpTracker  JdwpTracker;
+
+struct JdwpTracker {
+    asocket       socket;
+    JdwpTracker*  next;
+    JdwpTracker*  prev;
+    int           need_update;
+};
+
+static JdwpTracker   _jdwp_trackers_list;
+
+
+static void
+jdwp_process_list_updated(void)
+{
+    char             buffer[1024];
+    int              len;
+    JdwpTracker*  t = _jdwp_trackers_list.next;
+
+    len = jdwp_process_list_msg(buffer, sizeof(buffer));
+
+    for ( ; t != &_jdwp_trackers_list; t = t->next ) {
+        apacket*  p    = get_apacket();
+        asocket*  peer = t->socket.peer;
+        memcpy(p->data, buffer, len);
+        p->len = len;
+        peer->enqueue( peer, p );
+    }
+}
+
+static void
+jdwp_tracker_close( asocket*  s )
+{
+    JdwpTracker*  tracker = (JdwpTracker*) s;
+    asocket*      peer    = s->peer;
+
+    if (peer) {
+        peer->peer = NULL;
+        peer->close(peer);
+    }
+
+    remove_socket(s);
+
+    tracker->prev->next = tracker->next;
+    tracker->next->prev = tracker->prev;
+
+    free(s);
+}
+
+static void
+jdwp_tracker_ready( asocket*  s )
+{
+    JdwpTracker*  t = (JdwpTracker*) s;
+
+    if (t->need_update) {
+        apacket*  p = get_apacket();
+        t->need_update = 0;
+        p->len = jdwp_process_list_msg((char*)p->data, sizeof(p->data));
+        s->peer->enqueue(s->peer, p);
+    }
+}
+
+static int
+jdwp_tracker_enqueue( asocket*  s, apacket*  p )
+{
+    /* you can't write to this socket */
+    put_apacket(p);
+    s->peer->close(s->peer);
+    return -1;
+}
+
+
+asocket*
+create_jdwp_tracker_service_socket( void )
+{
+    JdwpTracker*  t = calloc(sizeof(*t),1);
+
+    if (t == NULL)
+        return NULL;
+
+    t->next = &_jdwp_trackers_list;
+    t->prev = t->next->prev;
+
+    t->next->prev = t;
+    t->prev->next = t;
+
+    install_local_socket(&t->socket);
+
+    t->socket.ready   = jdwp_tracker_ready;
+    t->socket.enqueue = jdwp_tracker_enqueue;
+    t->socket.close   = jdwp_tracker_close;
+    t->need_update    = 1;
+
+    return &t->socket;
+}
+
+
+int
+init_jdwp(void)
+{
+    _jdwp_list.next = &_jdwp_list;
+    _jdwp_list.prev = &_jdwp_list;
+
+    _jdwp_trackers_list.next = &_jdwp_trackers_list;
+    _jdwp_trackers_list.prev = &_jdwp_trackers_list;
+
+    return jdwp_control_init( &_jdwp_control,
+                              JDWP_CONTROL_NAME,
+                              JDWP_CONTROL_NAME_LEN );
+}
+
+#endif /* !ADB_HOST */
+
diff --git a/package/utils/adbd/src/adb/mutex_list.h b/package/utils/adbd/src/adb/mutex_list.h
new file mode 100644
index 0000000..ff72751
--- /dev/null
+++ b/package/utils/adbd/src/adb/mutex_list.h
@@ -0,0 +1,25 @@
+/* the list of mutexes used by adb */
+/* #ifndef __MUTEX_LIST_H
+ * Do not use an include-guard. This file is included once to declare the locks
+ * and once in win32 to actually do the runtime initialization.
+ */
+#ifndef ADB_MUTEX
+#error ADB_MUTEX not defined when including this file
+#endif
+ADB_MUTEX(socket_list_lock)
+ADB_MUTEX(transport_lock)
+#if ADB_HOST
+ADB_MUTEX(local_transports_lock)
+#endif
+ADB_MUTEX(usb_lock)
+
+// Sadly logging to /data/adb/adb-... is not thread safe.
+//  After modifying adb.h::D() to count invocations:
+//   DEBUG(jpa):0:Handling main()
+//   DEBUG(jpa):1:[ usb_init - starting thread ]
+// (Oopsies, no :2:, and matching message is also gone.)
+//   DEBUG(jpa):3:[ usb_thread - opening device ]
+//   DEBUG(jpa):4:jdwp control socket started (10)
+ADB_MUTEX(D_lock)
+
+#undef ADB_MUTEX
diff --git a/package/utils/adbd/src/adb/protocol.txt b/package/utils/adbd/src/adb/protocol.txt
new file mode 100644
index 0000000..c9d3c24
--- /dev/null
+++ b/package/utils/adbd/src/adb/protocol.txt
@@ -0,0 +1,271 @@
+
+--- a replacement for aproto -------------------------------------------
+
+When it comes down to it, aproto's primary purpose is to forward
+various streams between the host computer and client device (in either
+direction).
+
+This replacement further simplifies the concept, reducing the protocol
+to an extremely straightforward model optimized to accomplish the
+forwarding of these streams and removing additional state or
+complexity.
+
+The host side becomes a simple comms bridge with no "UI", which will 
+be used by either commandline or interactive tools to communicate with 
+a device or emulator that is connected to the bridge.
+
+The protocol is designed to be straightforward and well-defined enough 
+that if it needs to be reimplemented in another environment (Java 
+perhaps), there should not problems ensuring perfect interoperability.
+
+The protocol discards the layering aproto has and should allow the 
+implementation to be much more robust.
+
+
+--- protocol overview and basics ---------------------------------------
+
+The transport layer deals in "messages", which consist of a 24 byte
+header followed (optionally) by a payload.  The header consists of 6
+32 bit words which are sent across the wire in little endian format.
+
+struct message {
+    unsigned command;       /* command identifier constant      */
+    unsigned arg0;          /* first argument                   */
+    unsigned arg1;          /* second argument                  */
+    unsigned data_length;   /* length of payload (0 is allowed) */
+    unsigned data_crc32;    /* crc32 of data payload            */
+    unsigned magic;         /* command ^ 0xffffffff             */
+};
+
+Receipt of an invalid message header, corrupt message payload, or an
+unrecognized command MUST result in the closing of the remote
+connection.  The protocol depends on shared state and any break in the
+message stream will result in state getting out of sync.
+
+The following sections describe the six defined message types in
+detail.  Their format is COMMAND(arg0, arg1, payload) where the payload
+is represented by a quoted string or an empty string if none should be
+sent.
+
+The identifiers "local-id" and "remote-id" are always relative to the
+*sender* of the message, so for a receiver, the meanings are effectively
+reversed.
+
+
+
+--- CONNECT(version, maxdata, "system-identity-string") ----------------
+
+The CONNECT message establishes the presence of a remote system.
+The version is used to ensure protocol compatibility and maxdata
+declares the maximum message body size that the remote system
+is willing to accept.
+
+Currently, version=0x01000000 and maxdata=4096
+
+Both sides send a CONNECT message when the connection between them is
+established.  Until a CONNECT message is received no other messages may
+be sent.  Any messages received before a CONNECT message MUST be ignored.
+
+If a CONNECT message is received with an unknown version or insufficiently
+large maxdata value, the connection with the other side must be closed.
+
+The system identity string should be "<systemtype>:<serialno>:<banner>"
+where systemtype is "bootloader", "device", or "host", serialno is some
+kind of unique ID (or empty), and banner is a human-readable version
+or identifier string.  The banner is used to transmit useful properties.
+
+
+--- AUTH(type, 0, "data") ----------------------------------------------
+
+The AUTH message informs the recipient that authentication is required to
+connect to the sender. If type is TOKEN(1), data is a random token that
+the recipient can sign with a private key. The recipient replies with an
+AUTH packet where type is SIGNATURE(2) and data is the signature. If the
+signature verification succeeds, the sender replies with a CONNECT packet.
+
+If the signature verification fails, the sender replies with a new AUTH
+packet and a new random token, so that the recipient can retry signing
+with a different private key.
+
+Once the recipient has tried all its private keys, it can reply with an
+AUTH packet where type is RSAPUBLICKEY(3) and data is the public key. If
+possible, an on-screen confirmation may be displayed for the user to
+confirm they want to install the public key on the device.
+
+
+--- OPEN(local-id, 0, "destination") -----------------------------------
+
+The OPEN message informs the recipient that the sender has a stream
+identified by local-id that it wishes to connect to the named
+destination in the message payload.  The local-id may not be zero.
+
+The OPEN message MUST result in either a READY message indicating that
+the connection has been established (and identifying the other end) or
+a CLOSE message, indicating failure.  An OPEN message also implies
+a READY message sent at the same time.
+
+Common destination naming conventions include:
+
+* "tcp:<host>:<port>" - host may be omitted to indicate localhost
+* "udp:<host>:<port>" - host may be omitted to indicate localhost
+* "local-dgram:<identifier>"
+* "local-stream:<identifier>"
+* "shell" - local shell service
+* "upload" - service for pushing files across (like aproto's /sync)
+* "fs-bridge" - FUSE protocol filesystem bridge
+
+
+--- READY(local-id, remote-id, "") -------------------------------------
+
+The READY message informs the recipient that the sender's stream
+identified by local-id is ready for write messages and that it is
+connected to the recipient's stream identified by remote-id.
+
+Neither the local-id nor the remote-id may be zero. 
+
+A READY message containing a remote-id which does not map to an open
+stream on the recipient's side is ignored.  The stream may have been
+closed while this message was in-flight.
+
+The local-id is ignored on all but the first READY message (where it
+is used to establish the connection).  Nonetheless, the local-id MUST
+not change on later READY messages sent to the same stream.
+
+
+
+--- WRITE(0, remote-id, "data") ----------------------------------------
+
+The WRITE message sends data to the recipient's stream identified by
+remote-id.  The payload MUST be <= maxdata in length.
+
+A WRITE message containing a remote-id which does not map to an open
+stream on the recipient's side is ignored.  The stream may have been
+closed while this message was in-flight.
+
+A WRITE message may not be sent until a READY message is received.
+Once a WRITE message is sent, an additional WRITE message may not be
+sent until another READY message has been received.  Recipients of
+a WRITE message that is in violation of this requirement will CLOSE
+the connection.
+
+
+--- CLOSE(local-id, remote-id, "") -------------------------------------
+
+The CLOSE message informs recipient that the connection between the
+sender's stream (local-id) and the recipient's stream (remote-id) is
+broken.  The remote-id MUST not be zero, but the local-id MAY be zero
+if this CLOSE indicates a failed OPEN.
+
+A CLOSE message containing a remote-id which does not map to an open
+stream on the recipient's side is ignored.  The stream may have
+already been closed by the recipient while this message was in-flight.
+
+The recipient should not respond to a CLOSE message in any way.  The
+recipient should cancel pending WRITEs or CLOSEs, but this is not a
+requirement, since they will be ignored.
+
+
+--- SYNC(online, sequence, "") -----------------------------------------
+
+The SYNC message is used by the io pump to make sure that stale
+outbound messages are discarded when the connection to the remote side
+is broken.  It is only used internally to the bridge and never valid
+to send across the wire.  
+
+* when the connection to the remote side goes offline, the io pump 
+  sends a SYNC(0, 0) and starts discarding all messages
+* when the connection to the remote side is established, the io pump
+  sends a SYNC(1, token) and continues to discard messages
+* when the io pump receives a matching SYNC(1, token), it once again
+  starts accepting messages to forward to the remote side
+
+
+--- message command constants ------------------------------------------
+
+#define A_SYNC 0x434e5953
+#define A_CNXN 0x4e584e43
+#define A_AUTH 0x48545541
+#define A_OPEN 0x4e45504f
+#define A_OKAY 0x59414b4f
+#define A_CLSE 0x45534c43
+#define A_WRTE 0x45545257
+
+
+
+--- implementation details ---------------------------------------------
+
+The core of the bridge program will use three threads.  One thread
+will be a select/epoll loop to handle io between various inbound and
+outbound connections and the connection to the remote side.
+
+The remote side connection will be implemented as two threads (one for
+reading, one for writing) and a datagram socketpair to provide the
+channel between the main select/epoll thread and the remote connection
+threadpair.  The reason for this is that for usb connections, the
+kernel interface on linux and osx does not allow you to do meaningful
+nonblocking IO.
+
+The endian swapping for the message headers will happen (as needed) in
+the remote connection threadpair and that the rest of the program will
+always treat message header values as native-endian.
+
+The bridge program will be able to have a number of mini-servers
+compiled in.  They will be published under known names (examples
+"shell", "fs-bridge", etc) and upon receiving an OPEN() to such a
+service, the bridge program will create a stream socketpair and spawn
+a thread or subprocess to handle the io.
+
+
+--- simplified / embedded implementation -------------------------------
+
+For limited environments, like the bootloader, it is allowable to
+support a smaller, fixed number of channels using pre-assigned channel
+ID numbers such that only one stream may be connected to a bootloader
+endpoint at any given time.  The protocol remains unchanged, but the
+"embedded" version of it is less dynamic.
+
+The bootloader will support two streams.  A "bootloader:debug" stream,
+which may be opened to get debug messages from the bootloader and a 
+"bootloader:control", stream which will support the set of basic 
+bootloader commands.
+
+Example command stream dialogues:  
+  "flash_kernel,2515049,........\n" "okay\n" 
+  "flash_ramdisk,5038,........\n" "fail,flash write error\n" 
+  "bogus_command......" <CLOSE>
+
+
+--- future expansion ---------------------------------------------------
+
+I plan on providing either a message or a special control stream so that
+the client device could ask the host computer to setup inbound socket
+translations on the fly on behalf of the client device.
+
+
+The initial design does handshaking to provide flow control, with a
+message flow that looks like:
+
+  >OPEN <READY >WRITE <READY >WRITE <READY >WRITE <CLOSE
+
+The far side may choose to issue the READY message as soon as it receives
+a WRITE or it may defer the READY until the write to the local stream
+succeeds.  A future version may want to do some level of windowing where
+multiple WRITEs may be sent without requiring individual READY acks.
+
+------------------------------------------------------------------------
+
+--- smartsockets -------------------------------------------------------
+
+Port 5037 is used for smart sockets which allow a client on the host
+side to request access to a service in the host adb daemon or in the
+remote (device) daemon.  The service is requested by ascii name,
+preceeded by a 4 digit hex length.  Upon successful connection an
+"OKAY" response is sent, otherwise a "FAIL" message is returned.  Once
+connected the client is talking to that (remote or local) service.
+
+client: <hex4> <service-name>
+server: "OKAY"
+
+client: <hex4> <service-name>
+server: "FAIL" <hex4> <reason>
+
diff --git a/package/utils/adbd/src/adb/remount_service.c b/package/utils/adbd/src/adb/remount_service.c
new file mode 100644
index 0000000..d3a649b
--- /dev/null
+++ b/package/utils/adbd/src/adb/remount_service.c
@@ -0,0 +1,119 @@
+/*
+ * 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 <sys/mount.h>
+#include <unistd.h>
+
+#include "sysdeps.h"
+
+#define  TRACE_TAG  TRACE_ADB
+#include "adb.h"
+
+
+static int system_ro = 1;
+
+/* Returns the device used to mount a directory in /proc/mounts */
+static char *find_mount(const char *dir)
+{
+    int fd;
+    int res;
+    char *token = NULL;
+    const char delims[] = "\n";
+    char buf[4096];
+
+    fd = unix_open("/proc/mounts", O_RDONLY);
+    if (fd < 0)
+        return NULL;
+
+    buf[sizeof(buf) - 1] = '\0';
+    adb_read(fd, buf, sizeof(buf) - 1);
+    adb_close(fd);
+
+    token = strtok(buf, delims);
+
+    while (token) {
+        char mount_dev[256];
+        char mount_dir[256];
+        int mount_freq;
+        int mount_passno;
+
+        res = sscanf(token, "%255s %255s %*s %*s %d %d\n",
+                     mount_dev, mount_dir, &mount_freq, &mount_passno);
+        mount_dev[255] = 0;
+        mount_dir[255] = 0;
+        if (res == 4 && (strcmp(dir, mount_dir) == 0))
+            return strdup(mount_dev);
+
+        token = strtok(NULL, delims);
+    }
+    return NULL;
+}
+
+/* Init mounts /system as read only, remount to enable writes. */
+static int remount_system()
+{
+    char *dev;
+    int fd;
+    int OFF = 0;
+
+    if (system_ro == 0) {
+        return 0;
+    }
+
+    dev = find_mount("/system");
+
+    if (!dev)
+        return -1;
+
+    fd = unix_open(dev, O_RDONLY);
+    if (fd < 0)
+        return -1;
+
+    ioctl(fd, BLKROSET, &OFF);
+    adb_close(fd);
+
+    system_ro = mount(dev, "/system", "none", MS_REMOUNT, NULL);
+
+    free(dev);
+
+    return system_ro;
+}
+
+static void write_string(int fd, const char* str)
+{
+    writex(fd, str, strlen(str));
+}
+
+void remount_service(int fd, void *cookie)
+{
+    int ret = remount_system();
+
+    if (!ret)
+       write_string(fd, "remount succeeded\n");
+    else {
+        char    buffer[200];
+        snprintf(buffer, sizeof(buffer), "remount failed: %s\n", strerror(errno));
+        write_string(fd, buffer);
+    }
+
+    adb_close(fd);
+}
+
diff --git a/package/utils/adbd/src/adb/rsa.c b/package/utils/adbd/src/adb/rsa.c
new file mode 100644
index 0000000..6e583e6
--- /dev/null
+++ b/package/utils/adbd/src/adb/rsa.c
@@ -0,0 +1,309 @@
+
+/* rsa.c
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are met:
+**     * Redistributions of source code must retain the above copyright
+**       notice, this list of conditions and the following disclaimer.
+**     * Redistributions in binary form must reproduce the above copyright
+**       notice, this list of conditions and the following disclaimer in the
+**       documentation and/or other materials provided with the distribution.
+**     * Neither the name of Google Inc. nor the names of its contributors may
+**       be used to endorse or promote products derived from this software
+**       without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR
+** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+** EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "mincrypt/rsa.h"
+#include "mincrypt/sha.h"
+#include "mincrypt/sha256.h"
+
+// a[] -= mod
+static void subM(const RSAPublicKey* key,
+                 uint32_t* a) {
+    int64_t A = 0;
+    int i;
+    for (i = 0; i < key->len; ++i) {
+        A += (uint64_t)a[i] - key->n[i];
+        a[i] = (uint32_t)A;
+        A >>= 32;
+    }
+}
+
+// return a[] >= mod
+static int geM(const RSAPublicKey* key,
+               const uint32_t* a) {
+    int i;
+    for (i = key->len; i;) {
+        --i;
+        if (a[i] < key->n[i]) return 0;
+        if (a[i] > key->n[i]) return 1;
+    }
+    return 1;  // equal
+}
+
+// montgomery c[] += a * b[] / R % mod
+static void montMulAdd(const RSAPublicKey* key,
+                       uint32_t* c,
+                       const uint32_t a,
+                       const uint32_t* b) {
+    uint64_t A = (uint64_t)a * b[0] + c[0];
+    uint32_t d0 = (uint32_t)A * key->n0inv;
+    uint64_t B = (uint64_t)d0 * key->n[0] + (uint32_t)A;
+    int i;
+
+    for (i = 1; i < key->len; ++i) {
+        A = (A >> 32) + (uint64_t)a * b[i] + c[i];
+        B = (B >> 32) + (uint64_t)d0 * key->n[i] + (uint32_t)A;
+        c[i - 1] = (uint32_t)B;
+    }
+
+    A = (A >> 32) + (B >> 32);
+
+    c[i - 1] = (uint32_t)A;
+
+    if (A >> 32) {
+        subM(key, c);
+    }
+}
+
+// montgomery c[] = a[] * b[] / R % mod
+static void montMul(const RSAPublicKey* key,
+                    uint32_t* c,
+                    const uint32_t* a,
+                    const uint32_t* b) {
+    int i;
+    for (i = 0; i < key->len; ++i) {
+        c[i] = 0;
+    }
+    for (i = 0; i < key->len; ++i) {
+        montMulAdd(key, c, a[i], b);
+    }
+}
+
+// In-place public exponentiation.
+// Input and output big-endian byte array in inout.
+static void modpow(const RSAPublicKey* key,
+                   uint8_t* inout) {
+    uint32_t a[RSANUMWORDS];
+    uint32_t aR[RSANUMWORDS];
+    uint32_t aaR[RSANUMWORDS];
+    uint32_t* aaa = 0;
+    int i;
+
+    // Convert from big endian byte array to little endian word array.
+    for (i = 0; i < key->len; ++i) {
+        uint32_t tmp =
+            (inout[((key->len - 1 - i) * 4) + 0] << 24) |
+            (inout[((key->len - 1 - i) * 4) + 1] << 16) |
+            (inout[((key->len - 1 - i) * 4) + 2] << 8) |
+            (inout[((key->len - 1 - i) * 4) + 3] << 0);
+        a[i] = tmp;
+    }
+
+    if (key->exponent == 65537) {
+        aaa = aaR;  // Re-use location.
+        montMul(key, aR, a, key->rr);  // aR = a * RR / R mod M
+        for (i = 0; i < 16; i += 2) {
+            montMul(key, aaR, aR, aR);  // aaR = aR * aR / R mod M
+            montMul(key, aR, aaR, aaR);  // aR = aaR * aaR / R mod M
+        }
+        montMul(key, aaa, aR, a);  // aaa = aR * a / R mod M
+    } else if (key->exponent == 3) {
+        aaa = aR;  // Re-use location.
+        montMul(key, aR, a, key->rr);  /* aR = a * RR / R mod M   */
+        montMul(key, aaR, aR, aR);     /* aaR = aR * aR / R mod M */
+        montMul(key, aaa, aaR, a);     /* aaa = aaR * a / R mod M */
+    }
+
+    // Make sure aaa < mod; aaa is at most 1x mod too large.
+    if (geM(key, aaa)) {
+        subM(key, aaa);
+    }
+
+    // Convert to bigendian byte array
+    for (i = key->len - 1; i >= 0; --i) {
+        uint32_t tmp = aaa[i];
+        *inout++ = tmp >> 24;
+        *inout++ = tmp >> 16;
+        *inout++ = tmp >> 8;
+        *inout++ = tmp >> 0;
+    }
+}
+
+// Expected PKCS1.5 signature padding bytes, for a keytool RSA signature.
+// Has the 0-length optional parameter encoded in the ASN1 (as opposed to the
+// other flavor which omits the optional parameter entirely). This code does not
+// accept signatures without the optional parameter.
+
+/*
+static const uint8_t sha_padding[RSANUMBYTES] = {
+    0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0x00, 0x30, 0x21, 0x30,
+    0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a,
+    0x05, 0x00, 0x04, 0x14,
+
+    // 20 bytes of hash go here.
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+};
+*/
+
+// SHA-1 of PKCS1.5 signature sha_padding for 2048 bit, as above.
+// At the location of the bytes of the hash all 00 are hashed.
+static const uint8_t kExpectedPadShaRsa2048[SHA_DIGEST_SIZE] = {
+    0xdc, 0xbd, 0xbe, 0x42, 0xd5, 0xf5, 0xa7, 0x2e,
+    0x6e, 0xfc, 0xf5, 0x5d, 0xaf, 0x9d, 0xea, 0x68,
+    0x7c, 0xfb, 0xf1, 0x67
+};
+
+/*
+static const uint8_t sha256_padding[RSANUMBYTES] = {
+    0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0x00, 0x30, 0x31, 0x30,
+    0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65,
+    0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20,
+
+    // 32 bytes of hash go here.
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+};
+*/
+
+// SHA-256 of PKCS1.5 signature sha256_padding for 2048 bit, as above.
+// At the location of the bytes of the hash all 00 are hashed.
+static const uint8_t kExpectedPadSha256Rsa2048[SHA256_DIGEST_SIZE] = {
+    0xab, 0x28, 0x8d, 0x8a, 0xd7, 0xd9, 0x59, 0x92,
+    0xba, 0xcc, 0xf8, 0x67, 0x20, 0xe1, 0x15, 0x2e,
+    0x39, 0x8d, 0x80, 0x36, 0xd6, 0x6f, 0xf0, 0xfd,
+    0x90, 0xe8, 0x7d, 0x8b, 0xe1, 0x7c, 0x87, 0x59,
+};
+
+// Verify a 2048-bit RSA PKCS1.5 signature against an expected hash.
+// Both e=3 and e=65537 are supported.  hash_len may be
+// SHA_DIGEST_SIZE (== 20) to indicate a SHA-1 hash, or
+// SHA256_DIGEST_SIZE (== 32) to indicate a SHA-256 hash.  No other
+// values are supported.
+//
+// Returns 1 on successful verification, 0 on failure.
+int RSA_verify(const RSAPublicKey *key,
+               const uint8_t *signature,
+               const int len,
+               const uint8_t *hash,
+               const int hash_len) {
+    uint8_t buf[RSANUMBYTES];
+    int i;
+    const uint8_t* padding_hash;
+
+    if (key->len != RSANUMWORDS) {
+        return 0;  // Wrong key passed in.
+    }
+
+    if (len != sizeof(buf)) {
+        return 0;  // Wrong input length.
+    }
+
+    if (hash_len != SHA_DIGEST_SIZE &&
+        hash_len != SHA256_DIGEST_SIZE) {
+        return 0;  // Unsupported hash.
+    }
+
+    if (key->exponent != 3 && key->exponent != 65537) {
+        return 0;  // Unsupported exponent.
+    }
+
+    for (i = 0; i < len; ++i) {  // Copy input to local workspace.
+        buf[i] = signature[i];
+    }
+
+    modpow(key, buf);  // In-place exponentiation.
+
+    // Xor sha portion, so it all becomes 00 iff equal.
+    for (i = len - hash_len; i < len; ++i) {
+        buf[i] ^= *hash++;
+    }
+
+    // Hash resulting buf, in-place.
+    switch (hash_len) {
+        case SHA_DIGEST_SIZE:
+            padding_hash = kExpectedPadShaRsa2048;
+            SHA_hash(buf, len, buf);
+            break;
+        case SHA256_DIGEST_SIZE:
+            padding_hash = kExpectedPadSha256Rsa2048;
+            SHA256_hash(buf, len, buf);
+            break;
+        default:
+            return 0;
+    }
+
+    // Compare against expected hash value.
+    for (i = 0; i < hash_len; ++i) {
+        if (buf[i] != padding_hash[i]) {
+            return 0;
+        }
+    }
+
+    return 1;  // All checked out OK.
+}
diff --git a/package/utils/adbd/src/adb/services.c b/package/utils/adbd/src/adb/services.c
new file mode 100644
index 0000000..0dbe4db
--- /dev/null
+++ b/package/utils/adbd/src/adb/services.c
@@ -0,0 +1,675 @@
+/*
+ * 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 <stddef.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include "sysdeps.h"
+
+#define  TRACE_TAG  TRACE_SERVICES
+#include "adb.h"
+#include "file_sync_service.h"
+
+#if ADB_HOST
+#  ifndef HAVE_WINSOCK
+#    include <netinet/in.h>
+#    include <netdb.h>
+#    include <sys/ioctl.h>
+#  endif
+#else
+#  include <cutils/android_reboot.h>
+#  include <cutils/properties.h>
+#endif
+
+typedef struct stinfo stinfo;
+
+struct stinfo {
+    void (*func)(int fd, void *cookie);
+    int fd;
+    void *cookie;
+};
+
+
+void *service_bootstrap_func(void *x)
+{
+    stinfo *sti = x;
+    sti->func(sti->fd, sti->cookie);
+    free(sti);
+    return 0;
+}
+
+#if !ADB_HOST
+
+void restart_root_service(int fd, void *cookie)
+{
+    char buf[100];
+    char value[PROPERTY_VALUE_MAX];
+
+    if (getuid() == 0) {
+        snprintf(buf, sizeof(buf), "adbd is already running as root\n");
+        writex(fd, buf, strlen(buf));
+        adb_close(fd);
+    } else {
+        property_get("ro.debuggable", value, "");
+        if (strcmp(value, "1") != 0) {
+            snprintf(buf, sizeof(buf), "adbd cannot run as root in production builds\n");
+            writex(fd, buf, strlen(buf));
+            adb_close(fd);
+            return;
+        }
+
+        property_set("service.adb.root", "1");
+        snprintf(buf, sizeof(buf), "restarting adbd as root\n");
+        writex(fd, buf, strlen(buf));
+        adb_close(fd);
+    }
+}
+
+void restart_tcp_service(int fd, void *cookie)
+{
+    char buf[100];
+    char value[PROPERTY_VALUE_MAX];
+    int port = (int) (uintptr_t) cookie;
+
+    if (port <= 0) {
+        snprintf(buf, sizeof(buf), "invalid port\n");
+        writex(fd, buf, strlen(buf));
+        adb_close(fd);
+        return;
+    }
+
+    snprintf(value, sizeof(value), "%d", port);
+    property_set("service.adb.tcp.port", value);
+    snprintf(buf, sizeof(buf), "restarting in TCP mode port: %d\n", port);
+    writex(fd, buf, strlen(buf));
+    adb_close(fd);
+}
+
+void restart_usb_service(int fd, void *cookie)
+{
+    char buf[100];
+
+    property_set("service.adb.tcp.port", "0");
+    snprintf(buf, sizeof(buf), "restarting in USB mode\n");
+    writex(fd, buf, strlen(buf));
+    adb_close(fd);
+}
+
+void reboot_service(int fd, void *arg)
+{
+    char buf[100];
+    char property_val[PROPERTY_VALUE_MAX];
+    int ret;
+
+    sync();
+
+    ret = snprintf(property_val, sizeof(property_val), "reboot,%s", (char *) arg);
+    if (ret >= (int) sizeof(property_val)) {
+        snprintf(buf, sizeof(buf), "reboot string too long. length=%d\n", ret);
+        writex(fd, buf, strlen(buf));
+        goto cleanup;
+    }
+
+    ret = property_set(ANDROID_RB_PROPERTY, property_val);
+    if (ret < 0) {
+        snprintf(buf, sizeof(buf), "reboot failed: %d\n", ret);
+        writex(fd, buf, strlen(buf));
+        goto cleanup;
+    }
+    // Don't return early. Give the reboot command time to take effect
+    // to avoid messing up scripts which do "adb reboot && adb wait-for-device"
+    while(1) { pause(); }
+cleanup:
+    free(arg);
+    adb_close(fd);
+}
+
+void reverse_service(int fd, void* arg)
+{
+    const char* command = arg;
+
+    if (handle_forward_request(command, kTransportAny, NULL, fd) < 0) {
+        sendfailmsg(fd, "not a reverse forwarding command");
+    }
+    free(arg);
+    adb_close(fd);
+}
+
+#endif
+
+static int create_service_thread(void (*func)(int, void *), void *cookie)
+{
+    stinfo *sti;
+    adb_thread_t t;
+    int s[2];
+
+    if(adb_socketpair(s)) {
+        printf("cannot create service socket pair\n");
+        return -1;
+    }
+
+    sti = malloc(sizeof(stinfo));
+    if(sti == 0) fatal("cannot allocate stinfo");
+    sti->func = func;
+    sti->cookie = cookie;
+    sti->fd = s[1];
+
+    if(adb_thread_create( &t, service_bootstrap_func, sti)){
+        free(sti);
+        adb_close(s[0]);
+        adb_close(s[1]);
+        printf("cannot create service thread\n");
+        return -1;
+    }
+
+    D("service thread started, %d:%d\n",s[0], s[1]);
+    return s[0];
+}
+
+#if !ADB_HOST
+
+static void init_subproc_child()
+{
+    setsid();
+
+    // Set OOM score adjustment to prevent killing
+    int fd = adb_open("/proc/self/oom_score_adj", O_WRONLY);
+    if (fd >= 0) {
+        adb_write(fd, "0", 1);
+        adb_close(fd);
+    } else {
+       D("adb: unable to update oom_score_adj\n");
+    }
+}
+
+static int create_subproc_pty(const char *cmd, const char *arg0, const char *arg1, pid_t *pid)
+{
+    D("create_subproc_pty(cmd=%s, arg0=%s, arg1=%s)\n", cmd, arg0, arg1);
+#ifdef HAVE_WIN32_PROC
+    fprintf(stderr, "error: create_subproc_pty not implemented on Win32 (%s %s %s)\n", cmd, arg0, arg1);
+    return -1;
+#else /* !HAVE_WIN32_PROC */
+    char *devname;
+    int ptm;
+
+    ptm = unix_open("/dev/ptmx", O_RDWR); // | O_NOCTTY);
+    if(ptm < 0){
+        printf("[ cannot open /dev/ptmx - %s ]\n",strerror(errno));
+        return -1;
+    }
+    fcntl(ptm, F_SETFD, FD_CLOEXEC);
+
+    if(grantpt(ptm) || unlockpt(ptm) ||
+       ((devname = (char*) ptsname(ptm)) == 0)){
+        printf("[ trouble with /dev/ptmx - %s ]\n", strerror(errno));
+        adb_close(ptm);
+        return -1;
+    }
+
+    *pid = fork();
+    if(*pid < 0) {
+        printf("- fork failed: %s -\n", strerror(errno));
+        adb_close(ptm);
+        return -1;
+    }
+
+    if (*pid == 0) {
+        init_subproc_child();
+
+        int pts = unix_open(devname, O_RDWR);
+        if (pts < 0) {
+            fprintf(stderr, "child failed to open pseudo-term slave: %s\n", devname);
+            exit(-1);
+        }
+
+        dup2(pts, STDIN_FILENO);
+        dup2(pts, STDOUT_FILENO);
+        dup2(pts, STDERR_FILENO);
+
+        adb_close(pts);
+        adb_close(ptm);
+
+        execl(cmd, cmd, arg0, arg1, NULL);
+        fprintf(stderr, "- exec '%s' failed: %s (%d) -\n",
+                cmd, strerror(errno), errno);
+        exit(-1);
+    } else {
+        return ptm;
+    }
+#endif /* !HAVE_WIN32_PROC */
+}
+
+static int create_subproc_raw(const char *cmd, const char *arg0, const char *arg1, pid_t *pid)
+{
+    D("create_subproc_raw(cmd=%s, arg0=%s, arg1=%s)\n", cmd, arg0, arg1);
+#ifdef HAVE_WIN32_PROC
+    fprintf(stderr, "error: create_subproc_raw not implemented on Win32 (%s %s %s)\n", cmd, arg0, arg1);
+    return -1;
+#else /* !HAVE_WIN32_PROC */
+
+    // 0 is parent socket, 1 is child socket
+    int sv[2];
+    if (unix_socketpair(AF_UNIX, SOCK_STREAM, 0, sv) < 0) {
+        printf("[ cannot create socket pair - %s ]\n", strerror(errno));
+        return -1;
+    }
+
+    *pid = fork();
+    if (*pid < 0) {
+        printf("- fork failed: %s -\n", strerror(errno));
+        adb_close(sv[0]);
+        adb_close(sv[1]);
+        return -1;
+    }
+
+    if (*pid == 0) {
+        adb_close(sv[0]);
+        init_subproc_child();
+
+        // Only hook up stdin/stdout; drop stderr
+        dup2(sv[1], STDIN_FILENO);
+        dup2(sv[1], STDOUT_FILENO);
+        adb_close(sv[1]);
+
+        execl(cmd, cmd, arg0, arg1, NULL);
+        fprintf(stderr, "- exec '%s' failed: %s (%d) -\n",
+                cmd, strerror(errno), errno);
+        exit(-1);
+    } else {
+        adb_close(sv[1]);
+        return sv[0];
+    }
+#endif /* !HAVE_WIN32_PROC */
+}
+#endif  /* !ABD_HOST */
+
+//#define ADB_PASSWD
+#if ADB_HOST
+#define SHELL_COMMAND "/bin/sh"
+#else
+#ifdef ADB_PASSWD
+#define SHELL_COMMAND "/bin/login"
+#else
+#define SHELL_COMMAND "/bin/sh"
+#endif //ADB_PASSWD
+#endif
+
+#if !ADB_HOST
+static void subproc_waiter_service(int fd, void *cookie)
+{
+    pid_t pid = (pid_t) (uintptr_t) cookie;
+
+    D("entered. fd=%d of pid=%d\n", fd, pid);
+    for (;;) {
+        int status;
+        pid_t p = waitpid(pid, &status, 0);
+        if (p == pid) {
+            D("fd=%d, post waitpid(pid=%d) status=%04x\n", fd, p, status);
+            if (WIFSIGNALED(status)) {
+                D("*** Killed by signal %d\n", WTERMSIG(status));
+                break;
+            } else if (!WIFEXITED(status)) {
+                D("*** Didn't exit!!. status %d\n", status);
+                break;
+            } else if (WEXITSTATUS(status) >= 0) {
+                D("*** Exit code %d\n", WEXITSTATUS(status));
+                break;
+            }
+         }
+    }
+    D("shell exited fd=%d of pid=%d err=%d\n", fd, pid, errno);
+    if (SHELL_EXIT_NOTIFY_FD >=0) {
+      int res;
+      res = writex(SHELL_EXIT_NOTIFY_FD, &fd, sizeof(fd));
+      D("notified shell exit via fd=%d for pid=%d res=%d errno=%d\n",
+        SHELL_EXIT_NOTIFY_FD, pid, res, errno);
+    }
+}
+
+static int create_subproc_thread(const char *name, const subproc_mode mode)
+{
+    stinfo *sti;
+    adb_thread_t t;
+    int ret_fd;
+    pid_t pid = -1;
+
+    const char *arg0, *arg1;
+    if (name == 0 || *name == 0) {
+#ifdef ADB_PASSWD
+        arg0 = "-p"; arg1 = 0;
+#else
+        arg0 = "-"; arg1 = 0;
+#endif //ADB_PASSWD
+    } else {
+        arg0 = "-c"; arg1 = name;
+    }
+
+    switch (mode) {
+    case SUBPROC_PTY:
+        ret_fd = create_subproc_pty(SHELL_COMMAND, arg0, arg1, &pid);
+        break;
+    case SUBPROC_RAW:
+        ret_fd = create_subproc_raw(SHELL_COMMAND, arg0, arg1, &pid);
+        break;
+    default:
+        fprintf(stderr, "invalid subproc_mode %d\n", mode);
+        return -1;
+    }
+    D("create_subproc ret_fd=%d pid=%d\n", ret_fd, pid);
+
+    sti = malloc(sizeof(stinfo));
+    if(sti == 0) fatal("cannot allocate stinfo");
+    sti->func = subproc_waiter_service;
+    sti->cookie = (void*) (uintptr_t) pid;
+    sti->fd = ret_fd;
+
+    if (adb_thread_create(&t, service_bootstrap_func, sti)) {
+        free(sti);
+        adb_close(ret_fd);
+        fprintf(stderr, "cannot create service thread\n");
+        return -1;
+    }
+
+    D("service thread started, fd=%d pid=%d\n", ret_fd, pid);
+    return ret_fd;
+}
+#endif
+
+int service_to_fd(const char *name)
+{
+    int ret = -1;
+
+    if(!strncmp(name, "tcp:", 4)) {
+        int port = atoi(name + 4);
+        name = strchr(name + 4, ':');
+        if(name == 0) {
+            ret = socket_loopback_client(port, SOCK_STREAM);
+            if (ret >= 0)
+                disable_tcp_nagle(ret);
+        } else {
+#if ADB_HOST
+            ret = socket_network_client(name + 1, port, SOCK_STREAM);
+#else
+            return -1;
+#endif
+        }
+#ifndef HAVE_WINSOCK   /* winsock doesn't implement unix domain sockets */
+    } else if(!strncmp(name, "local:", 6)) {
+        ret = socket_local_client(name + 6,
+                ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
+    } else if(!strncmp(name, "localreserved:", 14)) {
+        ret = socket_local_client(name + 14,
+                ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
+    } else if(!strncmp(name, "localabstract:", 14)) {
+        ret = socket_local_client(name + 14,
+                ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
+    } else if(!strncmp(name, "localfilesystem:", 16)) {
+        ret = socket_local_client(name + 16,
+                ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM);
+#endif
+#if !ADB_HOST
+    } else if(!strncmp("dev:", name, 4)) {
+        ret = unix_open(name + 4, O_RDWR);
+    } else if(!strncmp(name, "framebuffer:", 12)) {
+        ret = create_service_thread(framebuffer_service, 0);
+    } else if (!strncmp(name, "jdwp:", 5)) {
+        ret = create_jdwp_connection_fd(atoi(name+5));
+    } else if(!HOST && !strncmp(name, "shell:", 6)) {
+        ret = create_subproc_thread(name + 6, SUBPROC_PTY);
+    } else if(!HOST && !strncmp(name, "exec:", 5)) {
+        ret = create_subproc_thread(name + 5, SUBPROC_RAW);
+    } else if(!strncmp(name, "sync:", 5)) {
+        ret = create_service_thread(file_sync_service, NULL);
+    } else if(!strncmp(name, "remount:", 8)) {
+        ret = create_service_thread(remount_service, NULL);
+    } else if(!strncmp(name, "reboot:", 7)) {
+        void* arg = strdup(name + 7);
+        if (arg == NULL) return -1;
+        ret = create_service_thread(reboot_service, arg);
+    } else if(!strncmp(name, "root:", 5)) {
+        ret = create_service_thread(restart_root_service, NULL);
+    } else if(!strncmp(name, "backup:", 7)) {
+        char* arg = strdup(name + 7);
+        if (arg == NULL) return -1;
+        char* c = arg;
+        for (; *c != '\0'; c++) {
+            if (*c == ':')
+                *c = ' ';
+        }
+        char* cmd;
+        if (asprintf(&cmd, "/system/bin/bu backup %s", arg) != -1) {
+            ret = create_subproc_thread(cmd, SUBPROC_RAW);
+            free(cmd);
+        }
+        free(arg);
+    } else if(!strncmp(name, "restore:", 8)) {
+        ret = create_subproc_thread("/system/bin/bu restore", SUBPROC_RAW);
+    } else if(!strncmp(name, "tcpip:", 6)) {
+        int port;
+        if (sscanf(name + 6, "%d", &port) == 0) {
+            port = 0;
+        }
+        ret = create_service_thread(restart_tcp_service, (void *) (uintptr_t) port);
+    } else if(!strncmp(name, "usb:", 4)) {
+        ret = create_service_thread(restart_usb_service, NULL);
+    } else if (!strncmp(name, "reverse:", 8)) {
+        char* cookie = strdup(name + 8);
+        if (cookie == NULL) {
+            ret = -1;
+        } else {
+            ret = create_service_thread(reverse_service, cookie);
+            if (ret < 0) {
+                free(cookie);
+            }
+        }
+#endif
+    }
+    if (ret >= 0) {
+        close_on_exec(ret);
+    }
+    return ret;
+}
+
+#if ADB_HOST
+struct state_info {
+    transport_type transport;
+    char* serial;
+    int state;
+};
+
+static void wait_for_state(int fd, void* cookie)
+{
+    struct state_info* sinfo = cookie;
+    char* err = "unknown error";
+
+    D("wait_for_state %d\n", sinfo->state);
+
+    atransport *t = acquire_one_transport(sinfo->state, sinfo->transport, sinfo->serial, &err);
+    if(t != 0) {
+        writex(fd, "OKAY", 4);
+    } else {
+        sendfailmsg(fd, err);
+    }
+
+    if (sinfo->serial)
+        free(sinfo->serial);
+    free(sinfo);
+    adb_close(fd);
+    D("wait_for_state is done\n");
+}
+
+static void connect_device(char* host, char* buffer, int buffer_size)
+{
+    int port, fd;
+    char* portstr = strchr(host, ':');
+    char hostbuf[100];
+    char serial[100];
+    int ret;
+
+    strncpy(hostbuf, host, sizeof(hostbuf) - 1);
+    if (portstr) {
+        if (portstr - host >= (ptrdiff_t)sizeof(hostbuf)) {
+            snprintf(buffer, buffer_size, "bad host name %s", host);
+            return;
+        }
+        // zero terminate the host at the point we found the colon
+        hostbuf[portstr - host] = 0;
+        if (sscanf(portstr + 1, "%d", &port) == 0) {
+            snprintf(buffer, buffer_size, "bad port number %s", portstr);
+            return;
+        }
+    } else {
+        port = DEFAULT_ADB_LOCAL_TRANSPORT_PORT;
+    }
+
+    snprintf(serial, sizeof(serial), "%s:%d", hostbuf, port);
+
+    fd = socket_network_client_timeout(hostbuf, port, SOCK_STREAM, 10);
+    if (fd < 0) {
+        snprintf(buffer, buffer_size, "unable to connect to %s:%d", host, port);
+        return;
+    }
+
+    D("client: connected on remote on fd %d\n", fd);
+    close_on_exec(fd);
+    disable_tcp_nagle(fd);
+
+    ret = register_socket_transport(fd, serial, port, 0);
+    if (ret < 0) {
+        adb_close(fd);
+        snprintf(buffer, buffer_size, "already connected to %s", serial);
+    } else {
+        snprintf(buffer, buffer_size, "connected to %s", serial);
+    }
+}
+
+void connect_emulator(char* port_spec, char* buffer, int buffer_size)
+{
+    char* port_separator = strchr(port_spec, ',');
+    if (!port_separator) {
+        snprintf(buffer, buffer_size,
+                "unable to parse '%s' as <console port>,<adb port>",
+                port_spec);
+        return;
+    }
+
+    // Zero-terminate console port and make port_separator point to 2nd port.
+    *port_separator++ = 0;
+    int console_port = strtol(port_spec, NULL, 0);
+    int adb_port = strtol(port_separator, NULL, 0);
+    if (!(console_port > 0 && adb_port > 0)) {
+        *(port_separator - 1) = ',';
+        snprintf(buffer, buffer_size,
+                "Invalid port numbers: Expected positive numbers, got '%s'",
+                port_spec);
+        return;
+    }
+
+    /* Check if the emulator is already known.
+     * Note: There's a small but harmless race condition here: An emulator not
+     * present just yet could be registered by another invocation right
+     * after doing this check here. However, local_connect protects
+     * against double-registration too. From here, a better error message
+     * can be produced. In the case of the race condition, the very specific
+     * error message won't be shown, but the data doesn't get corrupted. */
+    atransport* known_emulator = find_emulator_transport_by_adb_port(adb_port);
+    if (known_emulator != NULL) {
+        snprintf(buffer, buffer_size,
+                "Emulator on port %d already registered.", adb_port);
+        return;
+    }
+
+    /* Check if more emulators can be registered. Similar unproblematic
+     * race condition as above. */
+    int candidate_slot = get_available_local_transport_index();
+    if (candidate_slot < 0) {
+        snprintf(buffer, buffer_size, "Cannot accept more emulators.");
+        return;
+    }
+
+    /* Preconditions met, try to connect to the emulator. */
+    if (!local_connect_arbitrary_ports(console_port, adb_port)) {
+        snprintf(buffer, buffer_size,
+                "Connected to emulator on ports %d,%d", console_port, adb_port);
+    } else {
+        snprintf(buffer, buffer_size,
+                "Could not connect to emulator on ports %d,%d",
+                console_port, adb_port);
+    }
+}
+
+static void connect_service(int fd, void* cookie)
+{
+    char buf[4096];
+    char resp[4096];
+    char *host = cookie;
+
+    if (!strncmp(host, "emu:", 4)) {
+        connect_emulator(host + 4, buf, sizeof(buf));
+    } else {
+        connect_device(host, buf, sizeof(buf));
+    }
+
+    // Send response for emulator and device
+    snprintf(resp, sizeof(resp), "%04x%s",(unsigned)strlen(buf), buf);
+    writex(fd, resp, strlen(resp));
+    adb_close(fd);
+}
+#endif
+
+#if ADB_HOST
+asocket*  host_service_to_socket(const char*  name, const char *serial)
+{
+    if (!strcmp(name,"track-devices")) {
+        return create_device_tracker();
+    } else if (!strncmp(name, "wait-for-", strlen("wait-for-"))) {
+        struct state_info* sinfo = malloc(sizeof(struct state_info));
+
+        if (serial)
+            sinfo->serial = strdup(serial);
+        else
+            sinfo->serial = NULL;
+
+        name += strlen("wait-for-");
+
+        if (!strncmp(name, "local", strlen("local"))) {
+            sinfo->transport = kTransportLocal;
+            sinfo->state = CS_DEVICE;
+        } else if (!strncmp(name, "usb", strlen("usb"))) {
+            sinfo->transport = kTransportUsb;
+            sinfo->state = CS_DEVICE;
+        } else if (!strncmp(name, "any", strlen("any"))) {
+            sinfo->transport = kTransportAny;
+            sinfo->state = CS_DEVICE;
+        } else {
+            free(sinfo);
+            return NULL;
+        }
+
+        int fd = create_service_thread(wait_for_state, sinfo);
+        return create_local_socket(fd);
+    } else if (!strncmp(name, "connect:", 8)) {
+        const char *host = name + 8;
+        int fd = create_service_thread(connect_service, (void *)host);
+        return create_local_socket(fd);
+    }
+    return NULL;
+}
+#endif /* ADB_HOST */
diff --git a/package/utils/adbd/src/adb/sha.c b/package/utils/adbd/src/adb/sha.c
new file mode 100644
index 0000000..7bc091d
--- /dev/null
+++ b/package/utils/adbd/src/adb/sha.c
@@ -0,0 +1,156 @@
+/* sha.c
+**
+** Copyright 2013, The Android Open Source Project
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are met:
+**     * Redistributions of source code must retain the above copyright
+**       notice, this list of conditions and the following disclaimer.
+**     * Redistributions in binary form must reproduce the above copyright
+**       notice, this list of conditions and the following disclaimer in the
+**       documentation and/or other materials provided with the distribution.
+**     * Neither the name of Google Inc. nor the names of its contributors may
+**       be used to endorse or promote products derived from this software
+**       without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR
+** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+** EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+// Optimized for minimal code size.
+
+#include "mincrypt/sha.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#define rol(bits, value) (((value) << (bits)) | ((value) >> (32 - (bits))))
+
+static void SHA1_Transform(SHA_CTX* ctx) {
+    uint32_t W[80];
+    uint32_t A, B, C, D, E;
+    uint8_t* p = ctx->buf;
+    int t;
+
+    for(t = 0; t < 16; ++t) {
+        uint32_t tmp =  *p++ << 24;
+        tmp |= *p++ << 16;
+        tmp |= *p++ << 8;
+        tmp |= *p++;
+        W[t] = tmp;
+    }
+
+    for(; t < 80; t++) {
+        W[t] = rol(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
+    }
+
+    A = ctx->state[0];
+    B = ctx->state[1];
+    C = ctx->state[2];
+    D = ctx->state[3];
+    E = ctx->state[4];
+
+    for(t = 0; t < 80; t++) {
+        uint32_t tmp = rol(5,A) + E + W[t];
+
+        if (t < 20)
+            tmp += (D^(B&(C^D))) + 0x5A827999;
+        else if ( t < 40)
+            tmp += (B^C^D) + 0x6ED9EBA1;
+        else if ( t < 60)
+            tmp += ((B&C)|(D&(B|C))) + 0x8F1BBCDC;
+        else
+            tmp += (B^C^D) + 0xCA62C1D6;
+
+        E = D;
+        D = C;
+        C = rol(30,B);
+        B = A;
+        A = tmp;
+    }
+
+    ctx->state[0] += A;
+    ctx->state[1] += B;
+    ctx->state[2] += C;
+    ctx->state[3] += D;
+    ctx->state[4] += E;
+}
+
+static const HASH_VTAB SHA_VTAB = {
+    SHA_init,
+    SHA_update,
+    SHA_final,
+    SHA_hash,
+    SHA_DIGEST_SIZE
+};
+
+void SHA_init(SHA_CTX* ctx) {
+    ctx->f = &SHA_VTAB;
+    ctx->state[0] = 0x67452301;
+    ctx->state[1] = 0xEFCDAB89;
+    ctx->state[2] = 0x98BADCFE;
+    ctx->state[3] = 0x10325476;
+    ctx->state[4] = 0xC3D2E1F0;
+    ctx->count = 0;
+}
+
+
+void SHA_update(SHA_CTX* ctx, const void* data, int len) {
+    int i = (int) (ctx->count & 63);
+    const uint8_t* p = (const uint8_t*)data;
+
+    ctx->count += len;
+
+    while (len--) {
+        ctx->buf[i++] = *p++;
+        if (i == 64) {
+            SHA1_Transform(ctx);
+            i = 0;
+        }
+    }
+}
+
+
+const uint8_t* SHA_final(SHA_CTX* ctx) {
+    uint8_t *p = ctx->buf;
+    uint64_t cnt = ctx->count * 8;
+    int i;
+
+    SHA_update(ctx, (uint8_t*)"\x80", 1);
+    while ((ctx->count & 63) != 56) {
+        SHA_update(ctx, (uint8_t*)"\0", 1);
+    }
+    for (i = 0; i < 8; ++i) {
+        uint8_t tmp = (uint8_t) (cnt >> ((7 - i) * 8));
+        SHA_update(ctx, &tmp, 1);
+    }
+
+    for (i = 0; i < 5; i++) {
+        uint32_t tmp = ctx->state[i];
+        *p++ = tmp >> 24;
+        *p++ = tmp >> 16;
+        *p++ = tmp >> 8;
+        *p++ = tmp >> 0;
+    }
+
+    return ctx->buf;
+}
+
+/* Convenience function */
+const uint8_t* SHA_hash(const void* data, int len, uint8_t* digest) {
+    SHA_CTX ctx;
+    SHA_init(&ctx);
+    SHA_update(&ctx, data, len);
+    memcpy(digest, SHA_final(&ctx), SHA_DIGEST_SIZE);
+    return digest;
+}
+
diff --git a/package/utils/adbd/src/adb/sha256.c b/package/utils/adbd/src/adb/sha256.c
new file mode 100644
index 0000000..ec968f8
--- /dev/null
+++ b/package/utils/adbd/src/adb/sha256.c
@@ -0,0 +1,185 @@
+/* sha256.c
+**
+** Copyright 2013, The Android Open Source Project
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are met:
+**     * Redistributions of source code must retain the above copyright
+**       notice, this list of conditions and the following disclaimer.
+**     * Redistributions in binary form must reproduce the above copyright
+**       notice, this list of conditions and the following disclaimer in the
+**       documentation and/or other materials provided with the distribution.
+**     * Neither the name of Google Inc. nor the names of its contributors may
+**       be used to endorse or promote products derived from this software
+**       without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR
+** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+** EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+// Optimized for minimal code size.
+
+#include "mincrypt/sha256.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#define ror(value, bits) (((value) >> (bits)) | ((value) << (32 - (bits))))
+#define shr(value, bits) ((value) >> (bits))
+
+static const uint32_t K[64] = {
+    0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
+    0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
+    0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
+    0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
+    0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
+    0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
+    0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
+    0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
+    0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
+    0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
+    0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
+    0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
+    0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
+    0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
+    0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
+    0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 };
+
+static void SHA256_Transform(SHA256_CTX* ctx) {
+    uint32_t W[64];
+    uint32_t A, B, C, D, E, F, G, H;
+    uint8_t* p = ctx->buf;
+    int t;
+
+    for(t = 0; t < 16; ++t) {
+        uint32_t tmp =  *p++ << 24;
+        tmp |= *p++ << 16;
+        tmp |= *p++ << 8;
+        tmp |= *p++;
+        W[t] = tmp;
+    }
+
+    for(; t < 64; t++) {
+        uint32_t s0 = ror(W[t-15], 7) ^ ror(W[t-15], 18) ^ shr(W[t-15], 3);
+        uint32_t s1 = ror(W[t-2], 17) ^ ror(W[t-2], 19) ^ shr(W[t-2], 10);
+        W[t] = W[t-16] + s0 + W[t-7] + s1;
+    }
+
+    A = ctx->state[0];
+    B = ctx->state[1];
+    C = ctx->state[2];
+    D = ctx->state[3];
+    E = ctx->state[4];
+    F = ctx->state[5];
+    G = ctx->state[6];
+    H = ctx->state[7];
+
+    for(t = 0; t < 64; t++) {
+        uint32_t s0 = ror(A, 2) ^ ror(A, 13) ^ ror(A, 22);
+        uint32_t maj = (A & B) ^ (A & C) ^ (B & C);
+        uint32_t t2 = s0 + maj;
+        uint32_t s1 = ror(E, 6) ^ ror(E, 11) ^ ror(E, 25);
+        uint32_t ch = (E & F) ^ ((~E) & G);
+        uint32_t t1 = H + s1 + ch + K[t] + W[t];
+
+        H = G;
+        G = F;
+        F = E;
+        E = D + t1;
+        D = C;
+        C = B;
+        B = A;
+        A = t1 + t2;
+    }
+
+    ctx->state[0] += A;
+    ctx->state[1] += B;
+    ctx->state[2] += C;
+    ctx->state[3] += D;
+    ctx->state[4] += E;
+    ctx->state[5] += F;
+    ctx->state[6] += G;
+    ctx->state[7] += H;
+}
+
+static const HASH_VTAB SHA256_VTAB = {
+    SHA256_init,
+    SHA256_update,
+    SHA256_final,
+    SHA256_hash,
+    SHA256_DIGEST_SIZE
+};
+
+void SHA256_init(SHA256_CTX* ctx) {
+    ctx->f = &SHA256_VTAB;
+    ctx->state[0] = 0x6a09e667;
+    ctx->state[1] = 0xbb67ae85;
+    ctx->state[2] = 0x3c6ef372;
+    ctx->state[3] = 0xa54ff53a;
+    ctx->state[4] = 0x510e527f;
+    ctx->state[5] = 0x9b05688c;
+    ctx->state[6] = 0x1f83d9ab;
+    ctx->state[7] = 0x5be0cd19;
+    ctx->count = 0;
+}
+
+
+void SHA256_update(SHA256_CTX* ctx, const void* data, int len) {
+    int i = (int) (ctx->count & 63);
+    const uint8_t* p = (const uint8_t*)data;
+
+    ctx->count += len;
+
+    while (len--) {
+        ctx->buf[i++] = *p++;
+        if (i == 64) {
+            SHA256_Transform(ctx);
+            i = 0;
+        }
+    }
+}
+
+
+const uint8_t* SHA256_final(SHA256_CTX* ctx) {
+    uint8_t *p = ctx->buf;
+    uint64_t cnt = ctx->count * 8;
+    int i;
+
+    SHA256_update(ctx, (uint8_t*)"\x80", 1);
+    while ((ctx->count & 63) != 56) {
+        SHA256_update(ctx, (uint8_t*)"\0", 1);
+    }
+    for (i = 0; i < 8; ++i) {
+        uint8_t tmp = (uint8_t) (cnt >> ((7 - i) * 8));
+        SHA256_update(ctx, &tmp, 1);
+    }
+
+    for (i = 0; i < 8; i++) {
+        uint32_t tmp = ctx->state[i];
+        *p++ = tmp >> 24;
+        *p++ = tmp >> 16;
+        *p++ = tmp >> 8;
+        *p++ = tmp >> 0;
+    }
+
+    return ctx->buf;
+}
+
+/* Convenience function */
+const uint8_t* SHA256_hash(const void* data, int len, uint8_t* digest) {
+    SHA256_CTX ctx;
+    SHA256_init(&ctx);
+    SHA256_update(&ctx, data, len);
+    memcpy(digest, SHA256_final(&ctx), SHA256_DIGEST_SIZE);
+    return digest;
+}
+
diff --git a/package/utils/adbd/src/adb/sockets.c b/package/utils/adbd/src/adb/sockets.c
new file mode 100644
index 0000000..de14a22
--- /dev/null
+++ b/package/utils/adbd/src/adb/sockets.c
@@ -0,0 +1,906 @@
+/*
+ * 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 <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "sysdeps.h"
+
+#define  TRACE_TAG  TRACE_SOCKETS
+#include "adb.h"
+
+ADB_MUTEX_DEFINE( socket_list_lock );
+
+static void local_socket_close_locked(asocket *s);
+
+int sendfailmsg(int fd, const char *reason)
+{
+    char buf[9];
+    int len;
+    len = strlen(reason);
+    if(len > 0xffff) len = 0xffff;
+    snprintf(buf, sizeof buf, "FAIL%04x", len);
+    if(writex(fd, buf, 8)) return -1;
+    return writex(fd, reason, len);
+}
+
+//extern int online;
+
+static unsigned local_socket_next_id = 1;
+
+static asocket local_socket_list = {
+    .next = &local_socket_list,
+    .prev = &local_socket_list,
+};
+
+/* the the list of currently closing local sockets.
+** these have no peer anymore, but still packets to
+** write to their fd.
+*/
+static asocket local_socket_closing_list = {
+    .next = &local_socket_closing_list,
+    .prev = &local_socket_closing_list,
+};
+
+// Parse the global list of sockets to find one with id |local_id|.
+// If |peer_id| is not 0, also check that it is connected to a peer
+// with id |peer_id|. Returns an asocket handle on success, NULL on failure.
+asocket *find_local_socket(unsigned local_id, unsigned peer_id)
+{
+    asocket *s;
+    asocket *result = NULL;
+
+    adb_mutex_lock(&socket_list_lock);
+    for (s = local_socket_list.next; s != &local_socket_list; s = s->next) {
+        if (s->id != local_id)
+            continue;
+        if (peer_id == 0 || (s->peer && s->peer->id == peer_id)) {
+            result = s;
+        }
+        break;
+    }
+    adb_mutex_unlock(&socket_list_lock);
+
+    return result;
+}
+
+static void
+insert_local_socket(asocket*  s, asocket*  list)
+{
+    s->next       = list;
+    s->prev       = s->next->prev;
+    s->prev->next = s;
+    s->next->prev = s;
+}
+
+
+void install_local_socket(asocket *s)
+{
+    adb_mutex_lock(&socket_list_lock);
+
+    s->id = local_socket_next_id++;
+
+    // Socket ids should never be 0.
+    if (local_socket_next_id == 0)
+      local_socket_next_id = 1;
+
+    insert_local_socket(s, &local_socket_list);
+
+    adb_mutex_unlock(&socket_list_lock);
+}
+
+void remove_socket(asocket *s)
+{
+    // socket_list_lock should already be held
+    if (s->prev && s->next)
+    {
+        s->prev->next = s->next;
+        s->next->prev = s->prev;
+        s->next = 0;
+        s->prev = 0;
+        s->id = 0;
+    }
+}
+
+void close_all_sockets(atransport *t)
+{
+    asocket *s;
+
+        /* this is a little gross, but since s->close() *will* modify
+        ** the list out from under you, your options are limited.
+        */
+    adb_mutex_lock(&socket_list_lock);
+restart:
+    for(s = local_socket_list.next; s != &local_socket_list; s = s->next){
+        if(s->transport == t || (s->peer && s->peer->transport == t)) {
+            local_socket_close_locked(s);
+            goto restart;
+        }
+    }
+    adb_mutex_unlock(&socket_list_lock);
+}
+
+static int local_socket_enqueue(asocket *s, apacket *p)
+{
+    D("LS(%d): enqueue %d\n", s->id, p->len);
+
+    p->ptr = p->data;
+
+        /* if there is already data queue'd, we will receive
+        ** events when it's time to write.  just add this to
+        ** the tail
+        */
+    if(s->pkt_first) {
+        goto enqueue;
+    }
+
+        /* write as much as we can, until we
+        ** would block or there is an error/eof
+        */
+    while(p->len > 0) {
+        int r = adb_write(s->fd, p->ptr, p->len);
+        if(r > 0) {
+            p->len -= r;
+            p->ptr += r;
+            continue;
+        }
+        if((r == 0) || (errno != EAGAIN)) {
+            D( "LS(%d): not ready, errno=%d: %s\n", s->id, errno, strerror(errno) );
+            s->close(s);
+            return 1; /* not ready (error) */
+        } else {
+            break;
+        }
+    }
+
+    if(p->len == 0) {
+        put_apacket(p);
+        return 0; /* ready for more data */
+    }
+
+enqueue:
+    p->next = 0;
+    if(s->pkt_first) {
+        s->pkt_last->next = p;
+    } else {
+        s->pkt_first = p;
+    }
+    s->pkt_last = p;
+
+        /* make sure we are notified when we can drain the queue */
+    fdevent_add(&s->fde, FDE_WRITE);
+
+    return 1; /* not ready (backlog) */
+}
+
+static void local_socket_ready(asocket *s)
+{
+        /* far side is ready for data, pay attention to
+           readable events */
+    fdevent_add(&s->fde, FDE_READ);
+//    D("LS(%d): ready()\n", s->id);
+}
+
+static void local_socket_close(asocket *s)
+{
+    adb_mutex_lock(&socket_list_lock);
+    local_socket_close_locked(s);
+    adb_mutex_unlock(&socket_list_lock);
+}
+
+// be sure to hold the socket list lock when calling this
+static void local_socket_destroy(asocket  *s)
+{
+    apacket *p, *n;
+    int exit_on_close = s->exit_on_close;
+
+    D("LS(%d): destroying fde.fd=%d\n", s->id, s->fde.fd);
+
+        /* IMPORTANT: the remove closes the fd
+        ** that belongs to this socket
+        */
+    fdevent_remove(&s->fde);
+
+        /* dispose of any unwritten data */
+    for(p = s->pkt_first; p; p = n) {
+        D("LS(%d): discarding %d bytes\n", s->id, p->len);
+        n = p->next;
+        put_apacket(p);
+    }
+    remove_socket(s);
+    free(s);
+
+    if (exit_on_close) {
+        D("local_socket_destroy: exiting\n");
+        exit(1);
+    }
+}
+
+
+static void local_socket_close_locked(asocket *s)
+{
+    D("entered. LS(%d) fd=%d\n", s->id, s->fd);
+    if(s->peer) {
+        D("LS(%d): closing peer. peer->id=%d peer->fd=%d\n",
+          s->id, s->peer->id, s->peer->fd);
+        /* Note: it's important to call shutdown before disconnecting from
+         * the peer, this ensures that remote sockets can still get the id
+         * of the local socket they're connected to, to send a CLOSE()
+         * protocol event. */
+        if (s->peer->shutdown)
+          s->peer->shutdown(s->peer);
+        s->peer->peer = 0;
+        // tweak to avoid deadlock
+        if (s->peer->close == local_socket_close) {
+            local_socket_close_locked(s->peer);
+        } else {
+            s->peer->close(s->peer);
+        }
+        s->peer = 0;
+    }
+
+        /* If we are already closing, or if there are no
+        ** pending packets, destroy immediately
+        */
+    if (s->closing || s->pkt_first == NULL) {
+        int   id = s->id;
+        local_socket_destroy(s);
+        D("LS(%d): closed\n", id);
+        return;
+    }
+
+        /* otherwise, put on the closing list
+        */
+    D("LS(%d): closing\n", s->id);
+    s->closing = 1;
+    fdevent_del(&s->fde, FDE_READ);
+    remove_socket(s);
+    D("LS(%d): put on socket_closing_list fd=%d\n", s->id, s->fd);
+    insert_local_socket(s, &local_socket_closing_list);
+}
+
+static void local_socket_event_func(int fd, unsigned ev, void *_s)
+{
+    asocket *s = _s;
+
+    D("LS(%d): event_func(fd=%d(==%d), ev=%04x)\n", s->id, s->fd, fd, ev);
+
+    /* put the FDE_WRITE processing before the FDE_READ
+    ** in order to simplify the code.
+    */
+    if(ev & FDE_WRITE){
+        apacket *p;
+
+        while((p = s->pkt_first) != 0) {
+            while(p->len > 0) {
+                int r = adb_write(fd, p->ptr, p->len);
+                if(r > 0) {
+                    p->ptr += r;
+                    p->len -= r;
+                    continue;
+                }
+                if(r < 0) {
+                    /* returning here is ok because FDE_READ will
+                    ** be processed in the next iteration loop
+                    */
+                    if(errno == EAGAIN) return;
+                    if(errno == EINTR) continue;
+                }
+                D(" closing after write because r=%d and errno is %d\n", r, errno);
+                s->close(s);
+                return;
+            }
+
+            if(p->len == 0) {
+                s->pkt_first = p->next;
+                if(s->pkt_first == 0) s->pkt_last = 0;
+                put_apacket(p);
+            }
+        }
+
+            /* if we sent the last packet of a closing socket,
+            ** we can now destroy it.
+            */
+        if (s->closing) {
+            D(" closing because 'closing' is set after write\n");
+            s->close(s);
+            return;
+        }
+
+            /* no more packets queued, so we can ignore
+            ** writable events again and tell our peer
+            ** to resume writing
+            */
+        fdevent_del(&s->fde, FDE_WRITE);
+        s->peer->ready(s->peer);
+    }
+
+
+    if(ev & FDE_READ){
+        apacket *p = get_apacket();
+        unsigned char *x = p->data;
+        size_t avail = MAX_PAYLOAD;
+        int r;
+        int is_eof = 0;
+
+        while(avail > 0) {
+            r = adb_read(fd, x, avail);
+            D("LS(%d): post adb_read(fd=%d,...) r=%d (errno=%d) avail=%zu\n", s->id, s->fd, r, r<0?errno:0, avail);
+            if(r > 0) {
+                avail -= r;
+                x += r;
+                continue;
+            }
+            if(r < 0) {
+                if(errno == EAGAIN) break;
+                if(errno == EINTR) continue;
+            }
+
+                /* r = 0 or unhandled error */
+            is_eof = 1;
+            break;
+        }
+        D("LS(%d): fd=%d post avail loop. r=%d is_eof=%d forced_eof=%d\n",
+          s->id, s->fd, r, is_eof, s->fde.force_eof);
+        if((avail == MAX_PAYLOAD) || (s->peer == 0)) {
+            put_apacket(p);
+        } else {
+            p->len = MAX_PAYLOAD - avail;
+
+            r = s->peer->enqueue(s->peer, p);
+            D("LS(%d): fd=%d post peer->enqueue(). r=%d\n", s->id, s->fd, r);
+
+            if(r < 0) {
+                    /* error return means they closed us as a side-effect
+                    ** and we must return immediately.
+                    **
+                    ** note that if we still have buffered packets, the
+                    ** socket will be placed on the closing socket list.
+                    ** this handler function will be called again
+                    ** to process FDE_WRITE events.
+                    */
+                return;
+            }
+
+            if(r > 0) {
+                    /* if the remote cannot accept further events,
+                    ** we disable notification of READs.  They'll
+                    ** be enabled again when we get a call to ready()
+                    */
+                fdevent_del(&s->fde, FDE_READ);
+            }
+        }
+        /* Don't allow a forced eof if data is still there */
+        if((s->fde.force_eof && !r) || is_eof) {
+            D(" closing because is_eof=%d r=%d s->fde.force_eof=%d\n", is_eof, r, s->fde.force_eof);
+            s->close(s);
+        }
+    }
+
+    if(ev & FDE_ERROR){
+            /* this should be caught be the next read or write
+            ** catching it here means we may skip the last few
+            ** bytes of readable data.
+            */
+//        s->close(s);
+        D("LS(%d): FDE_ERROR (fd=%d)\n", s->id, s->fd);
+
+        return;
+    }
+}
+
+asocket *create_local_socket(int fd)
+{
+    asocket *s = calloc(1, sizeof(asocket));
+    if (s == NULL) fatal("cannot allocate socket");
+    s->fd = fd;
+    s->enqueue = local_socket_enqueue;
+    s->ready = local_socket_ready;
+    s->shutdown = NULL;
+    s->close = local_socket_close;
+    install_local_socket(s);
+
+    fdevent_install(&s->fde, fd, local_socket_event_func, s);
+/*    fdevent_add(&s->fde, FDE_ERROR); */
+    //fprintf(stderr, "Created local socket in create_local_socket \n");
+    D("LS(%d): created (fd=%d)\n", s->id, s->fd);
+    return s;
+}
+
+asocket *create_local_service_socket(const char *name)
+{
+    asocket *s;
+    int fd;
+
+#if !ADB_HOST
+    if (!strcmp(name,"jdwp")) {
+        return create_jdwp_service_socket();
+    }
+    if (!strcmp(name,"track-jdwp")) {
+        return create_jdwp_tracker_service_socket();
+    }
+#endif
+    fd = service_to_fd(name);
+    if(fd < 0) return 0;
+
+    s = create_local_socket(fd);
+    D("LS(%d): bound to '%s' via %d\n", s->id, name, fd);
+
+#if !ADB_HOST
+    if ((!strncmp(name, "root:", 5) && getuid() != 0)
+        || !strncmp(name, "usb:", 4)
+        || !strncmp(name, "tcpip:", 6)) {
+        D("LS(%d): enabling exit_on_close\n", s->id);
+        s->exit_on_close = 1;
+    }
+#endif
+
+    return s;
+}
+
+#if ADB_HOST
+static asocket *create_host_service_socket(const char *name, const char* serial)
+{
+    asocket *s;
+
+    s = host_service_to_socket(name, serial);
+
+    if (s != NULL) {
+        D("LS(%d) bound to '%s'\n", s->id, name);
+        return s;
+    }
+
+    return s;
+}
+#endif /* ADB_HOST */
+
+/* a Remote socket is used to send/receive data to/from a given transport object
+** it needs to be closed when the transport is forcibly destroyed by the user
+*/
+typedef struct aremotesocket {
+    asocket      socket;
+    adisconnect  disconnect;
+} aremotesocket;
+
+static int remote_socket_enqueue(asocket *s, apacket *p)
+{
+    D("entered remote_socket_enqueue RS(%d) WRITE fd=%d peer.fd=%d\n",
+      s->id, s->fd, s->peer->fd);
+    p->msg.command = A_WRTE;
+    p->msg.arg0 = s->peer->id;
+    p->msg.arg1 = s->id;
+    p->msg.data_length = p->len;
+    send_packet(p, s->transport);
+    return 1;
+}
+
+static void remote_socket_ready(asocket *s)
+{
+    D("entered remote_socket_ready RS(%d) OKAY fd=%d peer.fd=%d\n",
+      s->id, s->fd, s->peer->fd);
+    apacket *p = get_apacket();
+    p->msg.command = A_OKAY;
+    p->msg.arg0 = s->peer->id;
+    p->msg.arg1 = s->id;
+    send_packet(p, s->transport);
+}
+
+static void remote_socket_shutdown(asocket *s)
+{
+    D("entered remote_socket_shutdown RS(%d) CLOSE fd=%d peer->fd=%d\n",
+      s->id, s->fd, s->peer?s->peer->fd:-1);
+    apacket *p = get_apacket();
+    p->msg.command = A_CLSE;
+    if(s->peer) {
+        p->msg.arg0 = s->peer->id;
+    }
+    p->msg.arg1 = s->id;
+    send_packet(p, s->transport);
+}
+
+static void remote_socket_close(asocket *s)
+{
+    if (s->peer) {
+        s->peer->peer = 0;
+        D("RS(%d) peer->close()ing peer->id=%d peer->fd=%d\n",
+          s->id, s->peer->id, s->peer->fd);
+        s->peer->close(s->peer);
+    }
+    D("entered remote_socket_close RS(%d) CLOSE fd=%d peer->fd=%d\n",
+      s->id, s->fd, s->peer?s->peer->fd:-1);
+    D("RS(%d): closed\n", s->id);
+    remove_transport_disconnect( s->transport, &((aremotesocket*)s)->disconnect );
+    free(s);
+}
+
+static void remote_socket_disconnect(void*  _s, atransport*  t)
+{
+    asocket*  s    = _s;
+    asocket*  peer = s->peer;
+
+    D("remote_socket_disconnect RS(%d)\n", s->id);
+    if (peer) {
+        peer->peer = NULL;
+        peer->close(peer);
+    }
+    remove_transport_disconnect( s->transport, &((aremotesocket*)s)->disconnect );
+    free(s);
+}
+
+/* Create an asocket to exchange packets with a remote service through transport
+  |t|. Where |id| is the socket id of the corresponding service on the other
+   side of the transport (it is allocated by the remote side and _cannot_ be 0).
+   Returns a new non-NULL asocket handle. */
+asocket *create_remote_socket(unsigned id, atransport *t)
+{
+    asocket* s;
+    adisconnect* dis;
+
+    if (id == 0) fatal("invalid remote socket id (0)");
+    s = calloc(1, sizeof(aremotesocket));
+    dis = &((aremotesocket*)s)->disconnect;
+
+    if (s == NULL) fatal("cannot allocate socket");
+    s->id = id;
+    s->enqueue = remote_socket_enqueue;
+    s->ready = remote_socket_ready;
+    s->shutdown = remote_socket_shutdown;
+    s->close = remote_socket_close;
+    s->transport = t;
+
+    dis->func   = remote_socket_disconnect;
+    dis->opaque = s;
+    add_transport_disconnect( t, dis );
+    D("RS(%d): created\n", s->id);
+    return s;
+}
+
+void connect_to_remote(asocket *s, const char *destination)
+{
+    D("Connect_to_remote call RS(%d) fd=%d\n", s->id, s->fd);
+    apacket *p = get_apacket();
+    int len = strlen(destination) + 1;
+
+    if(len > (MAX_PAYLOAD-1)) {
+        fatal("destination oversized");
+    }
+
+    D("LS(%d): connect('%s')\n", s->id, destination);
+    p->msg.command = A_OPEN;
+    p->msg.arg0 = s->id;
+    p->msg.data_length = len;
+    strcpy((char*) p->data, destination);
+    send_packet(p, s->transport);
+}
+
+
+/* this is used by magic sockets to rig local sockets to
+   send the go-ahead message when they connect */
+static void local_socket_ready_notify(asocket *s)
+{
+    s->ready = local_socket_ready;
+    s->shutdown = NULL;
+    s->close = local_socket_close;
+    adb_write(s->fd, "OKAY", 4);
+    s->ready(s);
+}
+
+/* this is used by magic sockets to rig local sockets to
+   send the failure message if they are closed before
+   connected (to avoid closing them without a status message) */
+static void local_socket_close_notify(asocket *s)
+{
+    s->ready = local_socket_ready;
+    s->shutdown = NULL;
+    s->close = local_socket_close;
+    sendfailmsg(s->fd, "closed");
+    s->close(s);
+}
+
+unsigned unhex(unsigned char *s, int len)
+{
+    unsigned n = 0, c;
+
+    while(len-- > 0) {
+        switch((c = *s++)) {
+        case '0': case '1': case '2':
+        case '3': case '4': case '5':
+        case '6': case '7': case '8':
+        case '9':
+            c -= '0';
+            break;
+        case 'a': case 'b': case 'c':
+        case 'd': case 'e': case 'f':
+            c = c - 'a' + 10;
+            break;
+        case 'A': case 'B': case 'C':
+        case 'D': case 'E': case 'F':
+            c = c - 'A' + 10;
+            break;
+        default:
+            return 0xffffffff;
+        }
+
+        n = (n << 4) | c;
+    }
+
+    return n;
+}
+
+#define PREFIX(str) { str, sizeof(str) - 1 }
+static const struct prefix_struct {
+    const char *str;
+    const size_t len;
+} prefixes[] = {
+    PREFIX("usb:"),
+    PREFIX("product:"),
+    PREFIX("model:"),
+    PREFIX("device:"),
+};
+static const int num_prefixes = (sizeof(prefixes) / sizeof(prefixes[0]));
+
+/* skip_host_serial return the position in a string
+   skipping over the 'serial' parameter in the ADB protocol,
+   where parameter string may be a host:port string containing
+   the protocol delimiter (colon). */
+char *skip_host_serial(char *service) {
+    char *first_colon, *serial_end;
+    int i;
+
+    for (i = 0; i < num_prefixes; i++) {
+        if (!strncmp(service, prefixes[i].str, prefixes[i].len))
+            return strchr(service + prefixes[i].len, ':');
+    }
+
+    first_colon = strchr(service, ':');
+    if (!first_colon) {
+        /* No colon in service string. */
+        return NULL;
+    }
+    serial_end = first_colon;
+    if (isdigit(serial_end[1])) {
+        serial_end++;
+        while ((*serial_end) && isdigit(*serial_end)) {
+            serial_end++;
+        }
+        if ((*serial_end) != ':') {
+            // Something other than numbers was found, reset the end.
+            serial_end = first_colon;
+        }
+    }
+    return serial_end;
+}
+
+static int smart_socket_enqueue(asocket *s, apacket *p)
+{
+    unsigned len;
+#if ADB_HOST
+    char *service = NULL;
+    char* serial = NULL;
+    transport_type ttype = kTransportAny;
+#endif
+
+    D("SS(%d): enqueue %d\n", s->id, p->len);
+
+    if(s->pkt_first == 0) {
+        s->pkt_first = p;
+        s->pkt_last = p;
+    } else {
+        if((s->pkt_first->len + p->len) > MAX_PAYLOAD) {
+            D("SS(%d): overflow\n", s->id);
+            put_apacket(p);
+            goto fail;
+        }
+
+        memcpy(s->pkt_first->data + s->pkt_first->len,
+               p->data, p->len);
+        s->pkt_first->len += p->len;
+        put_apacket(p);
+
+        p = s->pkt_first;
+    }
+
+        /* don't bother if we can't decode the length */
+    if(p->len < 4) return 0;
+
+    len = unhex(p->data, 4);
+    if((len < 1) ||  (len > 1024)) {
+        D("SS(%d): bad size (%d)\n", s->id, len);
+        goto fail;
+    }
+
+    D("SS(%d): len is %d\n", s->id, len );
+        /* can't do anything until we have the full header */
+    if((len + 4) > p->len) {
+        D("SS(%d): waiting for %d more bytes\n", s->id, len+4 - p->len);
+        return 0;
+    }
+
+    p->data[len + 4] = 0;
+
+    D("SS(%d): '%s'\n", s->id, (char*) (p->data + 4));
+
+#if ADB_HOST
+    service = (char *)p->data + 4;
+    if(!strncmp(service, "host-serial:", strlen("host-serial:"))) {
+        char* serial_end;
+        service += strlen("host-serial:");
+
+        // serial number should follow "host:" and could be a host:port string.
+        serial_end = skip_host_serial(service);
+        if (serial_end) {
+            *serial_end = 0; // terminate string
+            serial = service;
+            service = serial_end + 1;
+        }
+    } else if (!strncmp(service, "host-usb:", strlen("host-usb:"))) {
+        ttype = kTransportUsb;
+        service += strlen("host-usb:");
+    } else if (!strncmp(service, "host-local:", strlen("host-local:"))) {
+        ttype = kTransportLocal;
+        service += strlen("host-local:");
+    } else if (!strncmp(service, "host:", strlen("host:"))) {
+        ttype = kTransportAny;
+        service += strlen("host:");
+    } else {
+        service = NULL;
+    }
+
+    if (service) {
+        asocket *s2;
+
+            /* some requests are handled immediately -- in that
+            ** case the handle_host_request() routine has sent
+            ** the OKAY or FAIL message and all we have to do
+            ** is clean up.
+            */
+        if(handle_host_request(service, ttype, serial, s->peer->fd, s) == 0) {
+                /* XXX fail message? */
+            D( "SS(%d): handled host service '%s'\n", s->id, service );
+            goto fail;
+        }
+        if (!strncmp(service, "transport", strlen("transport"))) {
+            D( "SS(%d): okay transport\n", s->id );
+            p->len = 0;
+            return 0;
+        }
+
+            /* try to find a local service with this name.
+            ** if no such service exists, we'll fail out
+            ** and tear down here.
+            */
+        s2 = create_host_service_socket(service, serial);
+        if(s2 == 0) {
+            D( "SS(%d): couldn't create host service '%s'\n", s->id, service );
+            sendfailmsg(s->peer->fd, "unknown host service");
+            goto fail;
+        }
+
+            /* we've connected to a local host service,
+            ** so we make our peer back into a regular
+            ** local socket and bind it to the new local
+            ** service socket, acknowledge the successful
+            ** connection, and close this smart socket now
+            ** that its work is done.
+            */
+        adb_write(s->peer->fd, "OKAY", 4);
+
+        s->peer->ready = local_socket_ready;
+        s->peer->shutdown = NULL;
+        s->peer->close = local_socket_close;
+        s->peer->peer = s2;
+        s2->peer = s->peer;
+        s->peer = 0;
+        D( "SS(%d): okay\n", s->id );
+        s->close(s);
+
+            /* initial state is "ready" */
+        s2->ready(s2);
+        return 0;
+    }
+#else /* !ADB_HOST */
+    if (s->transport == NULL) {
+        char* error_string = "unknown failure";
+        s->transport = acquire_one_transport (CS_ANY,
+                kTransportAny, NULL, &error_string);
+
+        if (s->transport == NULL) {
+            sendfailmsg(s->peer->fd, error_string);
+            goto fail;
+        }
+    }
+#endif
+
+    if(!(s->transport) || (s->transport->connection_state == CS_OFFLINE)) {
+           /* if there's no remote we fail the connection
+            ** right here and terminate it
+            */
+        sendfailmsg(s->peer->fd, "device offline (x)");
+        goto fail;
+    }
+
+
+        /* instrument our peer to pass the success or fail
+        ** message back once it connects or closes, then
+        ** detach from it, request the connection, and
+        ** tear down
+        */
+    s->peer->ready = local_socket_ready_notify;
+    s->peer->shutdown = NULL;
+    s->peer->close = local_socket_close_notify;
+    s->peer->peer = 0;
+        /* give him our transport and upref it */
+    s->peer->transport = s->transport;
+
+    connect_to_remote(s->peer, (char*) (p->data + 4));
+    s->peer = 0;
+    s->close(s);
+    return 1;
+
+fail:
+        /* we're going to close our peer as a side-effect, so
+        ** return -1 to signal that state to the local socket
+        ** who is enqueueing against us
+        */
+    s->close(s);
+    return -1;
+}
+
+static void smart_socket_ready(asocket *s)
+{
+    D("SS(%d): ready\n", s->id);
+}
+
+static void smart_socket_close(asocket *s)
+{
+    D("SS(%d): closed\n", s->id);
+    if(s->pkt_first){
+        put_apacket(s->pkt_first);
+    }
+    if(s->peer) {
+        s->peer->peer = 0;
+        s->peer->close(s->peer);
+        s->peer = 0;
+    }
+    free(s);
+}
+
+static asocket *create_smart_socket(void)
+{
+    D("Creating smart socket \n");
+    asocket *s = calloc(1, sizeof(asocket));
+    if (s == NULL) fatal("cannot allocate socket");
+    s->enqueue = smart_socket_enqueue;
+    s->ready = smart_socket_ready;
+    s->shutdown = NULL;
+    s->close = smart_socket_close;
+
+    D("SS(%d)\n", s->id);
+    return s;
+}
+
+void connect_to_smartsocket(asocket *s)
+{
+    D("Connecting to smart socket \n");
+    asocket *ss = create_smart_socket();
+    s->peer = ss;
+    ss->peer = s;
+    s->ready(s);
+}
diff --git a/package/utils/adbd/src/adb/sockets.dia b/package/utils/adbd/src/adb/sockets.dia
new file mode 100644
index 0000000..c626f20
--- /dev/null
+++ b/package/utils/adbd/src/adb/sockets.dia
Binary files differ
diff --git a/package/utils/adbd/src/adb/sysdeps.h b/package/utils/adbd/src/adb/sysdeps.h
new file mode 100644
index 0000000..ba4306f
--- /dev/null
+++ b/package/utils/adbd/src/adb/sysdeps.h
@@ -0,0 +1,523 @@
+/*
+ * 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.
+ */
+
+/* this file contains system-dependent definitions used by ADB
+ * they're related to threads, sockets and file descriptors
+ */
+#ifndef _ADB_SYSDEPS_H
+#define _ADB_SYSDEPS_H
+
+#ifdef __CYGWIN__
+#  undef _WIN32
+#endif
+
+#ifdef _WIN32
+
+#include <windows.h>
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#include <process.h>
+#include <fcntl.h>
+#include <io.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <ctype.h>
+
+#define OS_PATH_SEPARATOR '\\'
+#define OS_PATH_SEPARATOR_STR "\\"
+#define ENV_PATH_SEPARATOR_STR ";"
+
+typedef CRITICAL_SECTION          adb_mutex_t;
+
+#define  ADB_MUTEX_DEFINE(x)     adb_mutex_t   x
+
+/* declare all mutexes */
+/* For win32, adb_sysdeps_init() will do the mutex runtime initialization. */
+#define  ADB_MUTEX(x)   extern adb_mutex_t  x;
+#include "mutex_list.h"
+
+extern void  adb_sysdeps_init(void);
+
+static __inline__ void adb_mutex_lock( adb_mutex_t*  lock )
+{
+    EnterCriticalSection( lock );
+}
+
+static __inline__ void  adb_mutex_unlock( adb_mutex_t*  lock )
+{
+    LeaveCriticalSection( lock );
+}
+
+typedef struct { unsigned  tid; }  adb_thread_t;
+
+typedef  void*  (*adb_thread_func_t)(void*  arg);
+
+typedef  void (*win_thread_func_t)(void*  arg);
+
+static __inline__ int  adb_thread_create( adb_thread_t  *thread, adb_thread_func_t  func, void*  arg)
+{
+    thread->tid = _beginthread( (win_thread_func_t)func, 0, arg );
+    if (thread->tid == (unsigned)-1L) {
+        return -1;
+    }
+    return 0;
+}
+
+static __inline__ void  close_on_exec(int  fd)
+{
+    /* nothing really */
+}
+
+extern void  disable_tcp_nagle(int  fd);
+
+#define  lstat    stat   /* no symlinks on Win32 */
+
+#define  S_ISLNK(m)   0   /* no symlinks on Win32 */
+
+static __inline__  int    adb_unlink(const char*  path)
+{
+    int  rc = unlink(path);
+
+    if (rc == -1 && errno == EACCES) {
+        /* unlink returns EACCES when the file is read-only, so we first */
+        /* try to make it writable, then unlink again...                  */
+        rc = chmod(path, _S_IREAD|_S_IWRITE );
+        if (rc == 0)
+            rc = unlink(path);
+    }
+    return rc;
+}
+#undef  unlink
+#define unlink  ___xxx_unlink
+
+static __inline__ int  adb_mkdir(const char*  path, int mode)
+{
+	return _mkdir(path);
+}
+#undef   mkdir
+#define  mkdir  ___xxx_mkdir
+
+extern int  adb_open(const char*  path, int  options);
+extern int  adb_creat(const char*  path, int  mode);
+extern int  adb_read(int  fd, void* buf, int len);
+extern int  adb_write(int  fd, const void*  buf, int  len);
+extern int  adb_lseek(int  fd, int  pos, int  where);
+extern int  adb_shutdown(int  fd);
+extern int  adb_close(int  fd);
+
+static __inline__ int  unix_close(int fd)
+{
+    return close(fd);
+}
+#undef   close
+#define  close   ____xxx_close
+
+static __inline__  int  unix_read(int  fd, void*  buf, size_t  len)
+{
+    return read(fd, buf, len);
+}
+#undef   read
+#define  read  ___xxx_read
+
+static __inline__  int  unix_write(int  fd, const void*  buf, size_t  len)
+{
+    return write(fd, buf, len);
+}
+#undef   write
+#define  write  ___xxx_write
+
+static __inline__ int  adb_open_mode(const char* path, int options, int mode)
+{
+    return adb_open(path, options);
+}
+
+static __inline__ int  unix_open(const char*  path, int options,...)
+{
+    if ((options & O_CREAT) == 0)
+    {
+        return  open(path, options);
+    }
+    else
+    {
+        int      mode;
+        va_list  args;
+        va_start( args, options );
+        mode = va_arg( args, int );
+        va_end( args );
+        return open(path, options, mode);
+    }
+}
+#define  open    ___xxx_unix_open
+
+
+/* normally provided by <cutils/misc.h> */
+extern void*  load_file(const char*  pathname, unsigned*  psize);
+
+/* normally provided by <cutils/sockets.h> */
+extern int socket_loopback_client(int port, int type);
+extern int socket_network_client(const char *host, int port, int type);
+extern int socket_network_client_timeout(const char *host, int port, int type,
+                                         int timeout);
+extern int socket_loopback_server(int port, int type);
+extern int socket_inaddr_any_server(int port, int type);
+
+/* normally provided by "fdevent.h" */
+
+#define FDE_READ              0x0001
+#define FDE_WRITE             0x0002
+#define FDE_ERROR             0x0004
+#define FDE_DONT_CLOSE        0x0080
+
+typedef struct fdevent fdevent;
+
+typedef void (*fd_func)(int fd, unsigned events, void *userdata);
+
+fdevent *fdevent_create(int fd, fd_func func, void *arg);
+void     fdevent_destroy(fdevent *fde);
+void     fdevent_install(fdevent *fde, int fd, fd_func func, void *arg);
+void     fdevent_remove(fdevent *item);
+void     fdevent_set(fdevent *fde, unsigned events);
+void     fdevent_add(fdevent *fde, unsigned events);
+void     fdevent_del(fdevent *fde, unsigned events);
+void     fdevent_loop();
+
+struct fdevent {
+    fdevent *next;
+    fdevent *prev;
+
+    int fd;
+    int force_eof;
+
+    unsigned short state;
+    unsigned short events;
+
+    fd_func func;
+    void *arg;
+};
+
+static __inline__ void  adb_sleep_ms( int  mseconds )
+{
+    Sleep( mseconds );
+}
+
+extern int  adb_socket_accept(int  serverfd, struct sockaddr*  addr, socklen_t  *addrlen);
+
+#undef   accept
+#define  accept  ___xxx_accept
+
+static __inline__  int  adb_socket_setbufsize( int   fd, int  bufsize )
+{
+    int opt = bufsize;
+    return setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (const char*)&opt, sizeof(opt));
+}
+
+extern int  adb_socketpair( int  sv[2] );
+
+static __inline__  char*  adb_dirstart( const char*  path )
+{
+    char*  p  = strchr(path, '/');
+    char*  p2 = strchr(path, '\\');
+
+    if ( !p )
+        p = p2;
+    else if ( p2 && p2 > p )
+        p = p2;
+
+    return p;
+}
+
+static __inline__  char*  adb_dirstop( const char*  path )
+{
+    char*  p  = strrchr(path, '/');
+    char*  p2 = strrchr(path, '\\');
+
+    if ( !p )
+        p = p2;
+    else if ( p2 && p2 > p )
+        p = p2;
+
+    return p;
+}
+
+static __inline__  int  adb_is_absolute_host_path( const char*  path )
+{
+    return isalpha(path[0]) && path[1] == ':' && path[2] == '\\';
+}
+
+extern char*  adb_strtok_r(char *str, const char *delim, char **saveptr);
+
+#else /* !_WIN32 a.k.a. Unix */
+
+#include "fdevent.h"
+#include <cutils/sockets.h>
+#include <cutils/misc.h>
+#include <signal.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <pthread.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <string.h>
+#include <unistd.h>
+
+/*
+ * TEMP_FAILURE_RETRY is defined by some, but not all, versions of
+ * <unistd.h>. (Alas, it is not as standard as we'd hoped!) So, if it's
+ * not already defined, then define it here.
+ */
+#ifndef TEMP_FAILURE_RETRY
+/* Used to retry syscalls that can return EINTR. */
+#define TEMP_FAILURE_RETRY(exp) ({         \
+    typeof (exp) _rc;                      \
+    do {                                   \
+        _rc = (exp);                       \
+    } while (_rc == -1 && errno == EINTR); \
+    _rc; })
+#endif
+
+#define OS_PATH_SEPARATOR '/'
+#define OS_PATH_SEPARATOR_STR "/"
+#define ENV_PATH_SEPARATOR_STR ":"
+
+typedef  pthread_mutex_t          adb_mutex_t;
+
+#define  ADB_MUTEX_INITIALIZER    PTHREAD_MUTEX_INITIALIZER
+#define  adb_mutex_init           pthread_mutex_init
+#define  adb_mutex_lock           pthread_mutex_lock
+#define  adb_mutex_unlock         pthread_mutex_unlock
+#define  adb_mutex_destroy        pthread_mutex_destroy
+
+#define  ADB_MUTEX_DEFINE(m)      adb_mutex_t   m = PTHREAD_MUTEX_INITIALIZER
+
+#define  adb_cond_t               pthread_cond_t
+#define  adb_cond_init            pthread_cond_init
+#define  adb_cond_wait            pthread_cond_wait
+#define  adb_cond_broadcast       pthread_cond_broadcast
+#define  adb_cond_signal          pthread_cond_signal
+#define  adb_cond_destroy         pthread_cond_destroy
+
+/* declare all mutexes */
+#define  ADB_MUTEX(x)   extern adb_mutex_t  x;
+#include "mutex_list.h"
+
+static __inline__ void  close_on_exec(int  fd)
+{
+    fcntl( fd, F_SETFD, FD_CLOEXEC );
+}
+
+static __inline__ int  unix_open(const char*  path, int options,...)
+{
+    if ((options & O_CREAT) == 0)
+    {
+        return  TEMP_FAILURE_RETRY( open(path, options) );
+    }
+    else
+    {
+        int      mode;
+        va_list  args;
+        va_start( args, options );
+        mode = va_arg( args, int );
+        va_end( args );
+        return TEMP_FAILURE_RETRY( open( path, options, mode ) );
+    }
+}
+
+static __inline__ int  adb_open_mode( const char*  pathname, int  options, int  mode )
+{
+    return TEMP_FAILURE_RETRY( open( pathname, options, mode ) );
+}
+
+
+static __inline__ int  adb_open( const char*  pathname, int  options )
+{
+    int  fd = TEMP_FAILURE_RETRY( open( pathname, options ) );
+    if (fd < 0)
+        return -1;
+    close_on_exec( fd );
+    return fd;
+}
+#undef   open
+#define  open    ___xxx_open
+
+static __inline__ int  adb_shutdown(int fd)
+{
+    return shutdown(fd, SHUT_RDWR);
+}
+#undef   shutdown
+#define  shutdown   ____xxx_shutdown
+
+static __inline__ int  adb_close(int fd)
+{
+    return close(fd);
+}
+#undef   close
+#define  close   ____xxx_close
+
+
+static __inline__  int  adb_read(int  fd, void*  buf, size_t  len)
+{
+    return TEMP_FAILURE_RETRY( read( fd, buf, len ) );
+}
+
+#undef   read
+#define  read  ___xxx_read
+
+static __inline__  int  adb_write(int  fd, const void*  buf, size_t  len)
+{
+    return TEMP_FAILURE_RETRY( write( fd, buf, len ) );
+}
+#undef   write
+#define  write  ___xxx_write
+
+static __inline__ int   adb_lseek(int  fd, int  pos, int  where)
+{
+    return lseek(fd, pos, where);
+}
+#undef   lseek
+#define  lseek   ___xxx_lseek
+
+static __inline__  int    adb_unlink(const char*  path)
+{
+    return  unlink(path);
+}
+#undef  unlink
+#define unlink  ___xxx_unlink
+
+static __inline__  int  adb_creat(const char*  path, int  mode)
+{
+    int  fd = TEMP_FAILURE_RETRY( creat( path, mode ) );
+
+    if ( fd < 0 )
+        return -1;
+
+    close_on_exec(fd);
+    return fd;
+}
+#undef   creat
+#define  creat  ___xxx_creat
+
+static __inline__ int  adb_socket_accept(int  serverfd, struct sockaddr*  addr, socklen_t  *addrlen)
+{
+    int fd;
+
+    fd = TEMP_FAILURE_RETRY( accept( serverfd, addr, addrlen ) );
+    if (fd >= 0)
+        close_on_exec(fd);
+
+    return fd;
+}
+
+#undef   accept
+#define  accept  ___xxx_accept
+
+#define  unix_read   adb_read
+#define  unix_write  adb_write
+#define  unix_close  adb_close
+
+typedef  pthread_t                 adb_thread_t;
+
+typedef void*  (*adb_thread_func_t)( void*  arg );
+
+static __inline__ int  adb_thread_create( adb_thread_t  *pthread, adb_thread_func_t  start, void*  arg )
+{
+    pthread_attr_t   attr;
+
+    pthread_attr_init (&attr);
+    pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
+
+    return pthread_create( pthread, &attr, start, arg );
+}
+
+static __inline__  int  adb_socket_setbufsize( int   fd, int  bufsize )
+{
+    int opt = bufsize;
+    return setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
+}
+
+static __inline__ void  disable_tcp_nagle(int fd)
+{
+    int  on = 1;
+    setsockopt( fd, IPPROTO_TCP, TCP_NODELAY, (void*)&on, sizeof(on) );
+}
+
+
+static __inline__ int  unix_socketpair( int  d, int  type, int  protocol, int sv[2] )
+{
+    return socketpair( d, type, protocol, sv );
+}
+
+static __inline__ int  adb_socketpair( int  sv[2] )
+{
+    int  rc;
+
+    rc = unix_socketpair( AF_UNIX, SOCK_STREAM, 0, sv );
+    if (rc < 0)
+        return -1;
+
+    close_on_exec( sv[0] );
+    close_on_exec( sv[1] );
+    return 0;
+}
+
+#undef   socketpair
+#define  socketpair   ___xxx_socketpair
+
+static __inline__ void  adb_sleep_ms( int  mseconds )
+{
+    usleep( mseconds*1000 );
+}
+
+static __inline__ int  adb_mkdir(const char*  path, int mode)
+{
+    return mkdir(path, mode);
+}
+#undef   mkdir
+#define  mkdir  ___xxx_mkdir
+
+static __inline__ void  adb_sysdeps_init(void)
+{
+}
+
+static __inline__ char*  adb_dirstart(const char*  path)
+{
+    return strchr(path, '/');
+}
+
+static __inline__ char*  adb_dirstop(const char*  path)
+{
+    return strrchr(path, '/');
+}
+
+static __inline__  int  adb_is_absolute_host_path( const char*  path )
+{
+    return path[0] == '/';
+}
+
+static __inline__ char*  adb_strtok_r(char *str, const char *delim, char **saveptr)
+{
+    return strtok_r(str, delim, saveptr);
+}
+#undef   strtok_r
+#define  strtok_r  ___xxx_strtok_r
+
+#endif /* !_WIN32 */
+
+#endif /* _ADB_SYSDEPS_H */
diff --git a/package/utils/adbd/src/adb/sysdeps_win32.c b/package/utils/adbd/src/adb/sysdeps_win32.c
new file mode 100644
index 0000000..29f58ec
--- /dev/null
+++ b/package/utils/adbd/src/adb/sysdeps_win32.c
@@ -0,0 +1,2227 @@
+#include "sysdeps.h"
+#include <windows.h>
+#include <winsock2.h>
+#include <stdio.h>
+#include <errno.h>
+#define  TRACE_TAG  TRACE_SYSDEPS
+#include "adb.h"
+
+extern void fatal(const char *fmt, ...);
+
+#define assert(cond)  do { if (!(cond)) fatal( "assertion failed '%s' on %s:%ld\n", #cond, __FILE__, __LINE__ ); } while (0)
+
+/**************************************************************************/
+/**************************************************************************/
+/*****                                                                *****/
+/*****      replaces libs/cutils/load_file.c                          *****/
+/*****                                                                *****/
+/**************************************************************************/
+/**************************************************************************/
+
+void *load_file(const char *fn, unsigned *_sz)
+{
+    HANDLE    file;
+    char     *data;
+    DWORD     file_size;
+
+    file = CreateFile( fn,
+                       GENERIC_READ,
+                       FILE_SHARE_READ,
+                       NULL,
+                       OPEN_EXISTING,
+                       0,
+                       NULL );
+
+    if (file == INVALID_HANDLE_VALUE)
+        return NULL;
+
+    file_size = GetFileSize( file, NULL );
+    data      = NULL;
+
+    if (file_size > 0) {
+        data = (char*) malloc( file_size + 1 );
+        if (data == NULL) {
+            D("load_file: could not allocate %ld bytes\n", file_size );
+            file_size = 0;
+        } else {
+            DWORD  out_bytes;
+
+            if ( !ReadFile( file, data, file_size, &out_bytes, NULL ) ||
+                 out_bytes != file_size )
+            {
+                D("load_file: could not read %ld bytes from '%s'\n", file_size, fn);
+                free(data);
+                data      = NULL;
+                file_size = 0;
+            }
+        }
+    }
+    CloseHandle( file );
+
+    *_sz = (unsigned) file_size;
+    return  data;
+}
+
+/**************************************************************************/
+/**************************************************************************/
+/*****                                                                *****/
+/*****    common file descriptor handling                             *****/
+/*****                                                                *****/
+/**************************************************************************/
+/**************************************************************************/
+
+typedef const struct FHClassRec_*   FHClass;
+
+typedef struct FHRec_*          FH;
+
+typedef struct EventHookRec_*  EventHook;
+
+typedef struct FHClassRec_
+{
+    void (*_fh_init) ( FH  f );
+    int  (*_fh_close)( FH  f );
+    int  (*_fh_lseek)( FH  f, int  pos, int  origin );
+    int  (*_fh_read) ( FH  f, void*  buf, int  len );
+    int  (*_fh_write)( FH  f, const void*  buf, int  len );
+    void (*_fh_hook) ( FH  f, int  events, EventHook  hook );
+
+} FHClassRec;
+
+/* used to emulate unix-domain socket pairs */
+typedef struct SocketPairRec_*  SocketPair;
+
+typedef struct FHRec_
+{
+    FHClass    clazz;
+    int        used;
+    int        eof;
+    union {
+        HANDLE      handle;
+        SOCKET      socket;
+        SocketPair  pair;
+    } u;
+
+    HANDLE    event;
+    int       mask;
+
+    char  name[32];
+
+} FHRec;
+
+#define  fh_handle  u.handle
+#define  fh_socket  u.socket
+#define  fh_pair    u.pair
+
+#define  WIN32_FH_BASE    100
+
+#define  WIN32_MAX_FHS    128
+
+static adb_mutex_t   _win32_lock;
+static  FHRec        _win32_fhs[ WIN32_MAX_FHS ];
+static  int          _win32_fh_count;
+
+static FH
+_fh_from_int( int   fd )
+{
+    FH  f;
+
+    fd -= WIN32_FH_BASE;
+
+    if (fd < 0 || fd >= _win32_fh_count) {
+        D( "_fh_from_int: invalid fd %d\n", fd + WIN32_FH_BASE );
+        errno = EBADF;
+        return NULL;
+    }
+
+    f = &_win32_fhs[fd];
+
+    if (f->used == 0) {
+        D( "_fh_from_int: invalid fd %d\n", fd + WIN32_FH_BASE );
+        errno = EBADF;
+        return NULL;
+    }
+
+    return f;
+}
+
+
+static int
+_fh_to_int( FH  f )
+{
+    if (f && f->used && f >= _win32_fhs && f < _win32_fhs + WIN32_MAX_FHS)
+        return (int)(f - _win32_fhs) + WIN32_FH_BASE;
+
+    return -1;
+}
+
+static FH
+_fh_alloc( FHClass  clazz )
+{
+    int  nn;
+    FH   f = NULL;
+
+    adb_mutex_lock( &_win32_lock );
+
+    if (_win32_fh_count < WIN32_MAX_FHS) {
+        f = &_win32_fhs[ _win32_fh_count++ ];
+        goto Exit;
+    }
+
+    for (nn = 0; nn < WIN32_MAX_FHS; nn++) {
+        if ( _win32_fhs[nn].clazz == NULL) {
+            f = &_win32_fhs[nn];
+            goto Exit;
+        }
+    }
+    D( "_fh_alloc: no more free file descriptors\n" );
+Exit:
+    if (f) {
+        f->clazz = clazz;
+        f->used  = 1;
+        f->eof   = 0;
+        clazz->_fh_init(f);
+    }
+    adb_mutex_unlock( &_win32_lock );
+    return f;
+}
+
+
+static int
+_fh_close( FH   f )
+{
+    if ( f->used ) {
+        f->clazz->_fh_close( f );
+        f->used = 0;
+        f->eof  = 0;
+        f->clazz = NULL;
+    }
+    return 0;
+}
+
+/* forward definitions */
+static const FHClassRec   _fh_file_class;
+static const FHClassRec   _fh_socket_class;
+
+/**************************************************************************/
+/**************************************************************************/
+/*****                                                                *****/
+/*****    file-based descriptor handling                              *****/
+/*****                                                                *****/
+/**************************************************************************/
+/**************************************************************************/
+
+static void
+_fh_file_init( FH  f )
+{
+    f->fh_handle = INVALID_HANDLE_VALUE;
+}
+
+static int
+_fh_file_close( FH  f )
+{
+    CloseHandle( f->fh_handle );
+    f->fh_handle = INVALID_HANDLE_VALUE;
+    return 0;
+}
+
+static int
+_fh_file_read( FH  f,  void*  buf, int   len )
+{
+    DWORD  read_bytes;
+
+    if ( !ReadFile( f->fh_handle, buf, (DWORD)len, &read_bytes, NULL ) ) {
+        D( "adb_read: could not read %d bytes from %s\n", len, f->name );
+        errno = EIO;
+        return -1;
+    } else if (read_bytes < (DWORD)len) {
+        f->eof = 1;
+    }
+    return (int)read_bytes;
+}
+
+static int
+_fh_file_write( FH  f,  const void*  buf, int   len )
+{
+    DWORD  wrote_bytes;
+
+    if ( !WriteFile( f->fh_handle, buf, (DWORD)len, &wrote_bytes, NULL ) ) {
+        D( "adb_file_write: could not write %d bytes from %s\n", len, f->name );
+        errno = EIO;
+        return -1;
+    } else if (wrote_bytes < (DWORD)len) {
+        f->eof = 1;
+    }
+    return  (int)wrote_bytes;
+}
+
+static int
+_fh_file_lseek( FH  f, int  pos, int  origin )
+{
+    DWORD  method;
+    DWORD  result;
+
+    switch (origin)
+    {
+        case SEEK_SET:  method = FILE_BEGIN; break;
+        case SEEK_CUR:  method = FILE_CURRENT; break;
+        case SEEK_END:  method = FILE_END; break;
+        default:
+            errno = EINVAL;
+            return -1;
+    }
+
+    result = SetFilePointer( f->fh_handle, pos, NULL, method );
+    if (result == INVALID_SET_FILE_POINTER) {
+        errno = EIO;
+        return -1;
+    } else {
+        f->eof = 0;
+    }
+    return (int)result;
+}
+
+static void  _fh_file_hook( FH  f, int  event, EventHook  eventhook );  /* forward */
+
+static const FHClassRec  _fh_file_class =
+{
+    _fh_file_init,
+    _fh_file_close,
+    _fh_file_lseek,
+    _fh_file_read,
+    _fh_file_write,
+    _fh_file_hook
+};
+
+/**************************************************************************/
+/**************************************************************************/
+/*****                                                                *****/
+/*****    file-based descriptor handling                              *****/
+/*****                                                                *****/
+/**************************************************************************/
+/**************************************************************************/
+
+int  adb_open(const char*  path, int  options)
+{
+    FH  f;
+
+    DWORD  desiredAccess       = 0;
+    DWORD  shareMode           = FILE_SHARE_READ | FILE_SHARE_WRITE;
+
+    switch (options) {
+        case O_RDONLY:
+            desiredAccess = GENERIC_READ;
+            break;
+        case O_WRONLY:
+            desiredAccess = GENERIC_WRITE;
+            break;
+        case O_RDWR:
+            desiredAccess = GENERIC_READ | GENERIC_WRITE;
+            break;
+        default:
+            D("adb_open: invalid options (0x%0x)\n", options);
+            errno = EINVAL;
+            return -1;
+    }
+
+    f = _fh_alloc( &_fh_file_class );
+    if ( !f ) {
+        errno = ENOMEM;
+        return -1;
+    }
+
+    f->fh_handle = CreateFile( path, desiredAccess, shareMode, NULL, OPEN_EXISTING,
+                               0, NULL );
+
+    if ( f->fh_handle == INVALID_HANDLE_VALUE ) {
+        _fh_close(f);
+        D( "adb_open: could not open '%s':", path );
+        switch (GetLastError()) {
+            case ERROR_FILE_NOT_FOUND:
+                D( "file not found\n" );
+                errno = ENOENT;
+                return -1;
+
+            case ERROR_PATH_NOT_FOUND:
+                D( "path not found\n" );
+                errno = ENOTDIR;
+                return -1;
+
+            default:
+                D( "unknown error\n" );
+                errno = ENOENT;
+                return -1;
+        }
+    }
+
+    snprintf( f->name, sizeof(f->name), "%d(%s)", _fh_to_int(f), path );
+    D( "adb_open: '%s' => fd %d\n", path, _fh_to_int(f) );
+    return _fh_to_int(f);
+}
+
+/* ignore mode on Win32 */
+int  adb_creat(const char*  path, int  mode)
+{
+    FH  f;
+
+    f = _fh_alloc( &_fh_file_class );
+    if ( !f ) {
+        errno = ENOMEM;
+        return -1;
+    }
+
+    f->fh_handle = CreateFile( path, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
+                               NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
+                               NULL );
+
+    if ( f->fh_handle == INVALID_HANDLE_VALUE ) {
+        _fh_close(f);
+        D( "adb_creat: could not open '%s':", path );
+        switch (GetLastError()) {
+            case ERROR_FILE_NOT_FOUND:
+                D( "file not found\n" );
+                errno = ENOENT;
+                return -1;
+
+            case ERROR_PATH_NOT_FOUND:
+                D( "path not found\n" );
+                errno = ENOTDIR;
+                return -1;
+
+            default:
+                D( "unknown error\n" );
+                errno = ENOENT;
+                return -1;
+        }
+    }
+    snprintf( f->name, sizeof(f->name), "%d(%s)", _fh_to_int(f), path );
+    D( "adb_creat: '%s' => fd %d\n", path, _fh_to_int(f) );
+    return _fh_to_int(f);
+}
+
+
+int  adb_read(int  fd, void* buf, int len)
+{
+    FH     f = _fh_from_int(fd);
+
+    if (f == NULL) {
+        return -1;
+    }
+
+    return f->clazz->_fh_read( f, buf, len );
+}
+
+
+int  adb_write(int  fd, const void*  buf, int  len)
+{
+    FH     f = _fh_from_int(fd);
+
+    if (f == NULL) {
+        return -1;
+    }
+
+    return f->clazz->_fh_write(f, buf, len);
+}
+
+
+int  adb_lseek(int  fd, int  pos, int  where)
+{
+    FH     f = _fh_from_int(fd);
+
+    if (!f) {
+        return -1;
+    }
+
+    return f->clazz->_fh_lseek(f, pos, where);
+}
+
+
+int  adb_shutdown(int  fd)
+{
+    FH   f = _fh_from_int(fd);
+
+    if (!f) {
+        return -1;
+    }
+
+    D( "adb_shutdown: %s\n", f->name);
+    shutdown( f->fh_socket, SD_BOTH );
+    return 0;
+}
+
+
+int  adb_close(int  fd)
+{
+    FH   f = _fh_from_int(fd);
+
+    if (!f) {
+        return -1;
+    }
+
+    D( "adb_close: %s\n", f->name);
+    _fh_close(f);
+    return 0;
+}
+
+/**************************************************************************/
+/**************************************************************************/
+/*****                                                                *****/
+/*****    socket-based file descriptors                               *****/
+/*****                                                                *****/
+/**************************************************************************/
+/**************************************************************************/
+
+static void
+_socket_set_errno( void )
+{
+    switch (WSAGetLastError()) {
+    case 0:              errno = 0; break;
+    case WSAEWOULDBLOCK: errno = EAGAIN; break;
+    case WSAEINTR:       errno = EINTR; break;
+    default:
+        D( "_socket_set_errno: unhandled value %d\n", WSAGetLastError() );
+        errno = EINVAL;
+    }
+}
+
+static void
+_fh_socket_init( FH  f )
+{
+    f->fh_socket = INVALID_SOCKET;
+    f->event     = WSACreateEvent();
+    f->mask      = 0;
+}
+
+static int
+_fh_socket_close( FH  f )
+{
+    /* gently tell any peer that we're closing the socket */
+    shutdown( f->fh_socket, SD_BOTH );
+    closesocket( f->fh_socket );
+    f->fh_socket = INVALID_SOCKET;
+    CloseHandle( f->event );
+    f->mask = 0;
+    return 0;
+}
+
+static int
+_fh_socket_lseek( FH  f, int pos, int origin )
+{
+    errno = EPIPE;
+    return -1;
+}
+
+static int
+_fh_socket_read( FH  f, void*  buf, int  len )
+{
+    int  result = recv( f->fh_socket, buf, len, 0 );
+    if (result == SOCKET_ERROR) {
+        _socket_set_errno();
+        result = -1;
+    }
+    return  result;
+}
+
+static int
+_fh_socket_write( FH  f, const void*  buf, int  len )
+{
+    int  result = send( f->fh_socket, buf, len, 0 );
+    if (result == SOCKET_ERROR) {
+        _socket_set_errno();
+        result = -1;
+    }
+    return result;
+}
+
+static void  _fh_socket_hook( FH  f, int  event, EventHook  hook );  /* forward */
+
+static const FHClassRec  _fh_socket_class =
+{
+    _fh_socket_init,
+    _fh_socket_close,
+    _fh_socket_lseek,
+    _fh_socket_read,
+    _fh_socket_write,
+    _fh_socket_hook
+};
+
+/**************************************************************************/
+/**************************************************************************/
+/*****                                                                *****/
+/*****    replacement for libs/cutils/socket_xxxx.c                   *****/
+/*****                                                                *****/
+/**************************************************************************/
+/**************************************************************************/
+
+#include <winsock2.h>
+
+static int  _winsock_init;
+
+static void
+_cleanup_winsock( void )
+{
+    WSACleanup();
+}
+
+static void
+_init_winsock( void )
+{
+    if (!_winsock_init) {
+        WSADATA  wsaData;
+        int      rc = WSAStartup( MAKEWORD(2,2), &wsaData);
+        if (rc != 0) {
+            fatal( "adb: could not initialize Winsock\n" );
+        }
+        atexit( _cleanup_winsock );
+        _winsock_init = 1;
+    }
+}
+
+int socket_loopback_client(int port, int type)
+{
+    FH  f = _fh_alloc( &_fh_socket_class );
+    struct sockaddr_in addr;
+    SOCKET  s;
+
+    if (!f)
+        return -1;
+
+    if (!_winsock_init)
+        _init_winsock();
+
+    memset(&addr, 0, sizeof(addr));
+    addr.sin_family = AF_INET;
+    addr.sin_port = htons(port);
+    addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+
+    s = socket(AF_INET, type, 0);
+    if(s == INVALID_SOCKET) {
+        D("socket_loopback_client: could not create socket\n" );
+        _fh_close(f);
+        return -1;
+    }
+
+    f->fh_socket = s;
+    if(connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+        D("socket_loopback_client: could not connect to %s:%d\n", type != SOCK_STREAM ? "udp" : "tcp", port );
+        _fh_close(f);
+        return -1;
+    }
+    snprintf( f->name, sizeof(f->name), "%d(lo-client:%s%d)", _fh_to_int(f), type != SOCK_STREAM ? "udp:" : "", port );
+    D( "socket_loopback_client: port %d type %s => fd %d\n", port, type != SOCK_STREAM ? "udp" : "tcp", _fh_to_int(f) );
+    return _fh_to_int(f);
+}
+
+#define LISTEN_BACKLOG 4
+
+int socket_loopback_server(int port, int type)
+{
+    FH   f = _fh_alloc( &_fh_socket_class );
+    struct sockaddr_in addr;
+    SOCKET  s;
+    int  n;
+
+    if (!f) {
+        return -1;
+    }
+
+    if (!_winsock_init)
+        _init_winsock();
+
+    memset(&addr, 0, sizeof(addr));
+    addr.sin_family = AF_INET;
+    addr.sin_port = htons(port);
+    addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+
+    s = socket(AF_INET, type, 0);
+    if(s == INVALID_SOCKET) return -1;
+
+    f->fh_socket = s;
+
+    n = 1;
+    setsockopt(s, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (const char*)&n, sizeof(n));
+
+    if(bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+        _fh_close(f);
+        return -1;
+    }
+    if (type == SOCK_STREAM) {
+        int ret;
+
+        ret = listen(s, LISTEN_BACKLOG);
+        if (ret < 0) {
+            _fh_close(f);
+            return -1;
+        }
+    }
+    snprintf( f->name, sizeof(f->name), "%d(lo-server:%s%d)", _fh_to_int(f), type != SOCK_STREAM ? "udp:" : "", port );
+    D( "socket_loopback_server: port %d type %s => fd %d\n", port, type != SOCK_STREAM ? "udp" : "tcp", _fh_to_int(f) );
+    return _fh_to_int(f);
+}
+
+
+int socket_network_client(const char *host, int port, int type)
+{
+    FH  f = _fh_alloc( &_fh_socket_class );
+    struct hostent *hp;
+    struct sockaddr_in addr;
+    SOCKET s;
+
+    if (!f)
+        return -1;
+
+    if (!_winsock_init)
+        _init_winsock();
+
+    hp = gethostbyname(host);
+    if(hp == 0) {
+        _fh_close(f);
+        return -1;
+    }
+
+    memset(&addr, 0, sizeof(addr));
+    addr.sin_family = hp->h_addrtype;
+    addr.sin_port = htons(port);
+    memcpy(&addr.sin_addr, hp->h_addr, hp->h_length);
+
+    s = socket(hp->h_addrtype, type, 0);
+    if(s == INVALID_SOCKET) {
+        _fh_close(f);
+        return -1;
+    }
+    f->fh_socket = s;
+
+    if(connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+        _fh_close(f);
+        return -1;
+    }
+
+    snprintf( f->name, sizeof(f->name), "%d(net-client:%s%d)", _fh_to_int(f), type != SOCK_STREAM ? "udp:" : "", port );
+    D( "socket_network_client: host '%s' port %d type %s => fd %d\n", host, port, type != SOCK_STREAM ? "udp" : "tcp", _fh_to_int(f) );
+    return _fh_to_int(f);
+}
+
+
+int socket_network_client_timeout(const char *host, int port, int type, int timeout)
+{
+    // TODO: implement timeouts for Windows.
+    return socket_network_client(host, port, type);
+}
+
+
+int socket_inaddr_any_server(int port, int type)
+{
+    FH  f = _fh_alloc( &_fh_socket_class );
+    struct sockaddr_in addr;
+    SOCKET  s;
+    int n;
+
+    if (!f)
+        return -1;
+
+    if (!_winsock_init)
+        _init_winsock();
+
+    memset(&addr, 0, sizeof(addr));
+    addr.sin_family = AF_INET;
+    addr.sin_port = htons(port);
+    addr.sin_addr.s_addr = htonl(INADDR_ANY);
+
+    s = socket(AF_INET, type, 0);
+    if(s == INVALID_SOCKET) {
+        _fh_close(f);
+        return -1;
+    }
+
+    f->fh_socket = s;
+    n = 1;
+    setsockopt(s, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (const char*)&n, sizeof(n));
+
+    if(bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+        _fh_close(f);
+        return -1;
+    }
+
+    if (type == SOCK_STREAM) {
+        int ret;
+
+        ret = listen(s, LISTEN_BACKLOG);
+        if (ret < 0) {
+            _fh_close(f);
+            return -1;
+        }
+    }
+    snprintf( f->name, sizeof(f->name), "%d(any-server:%s%d)", _fh_to_int(f), type != SOCK_STREAM ? "udp:" : "", port );
+    D( "socket_inaddr_server: port %d type %s => fd %d\n", port, type != SOCK_STREAM ? "udp" : "tcp", _fh_to_int(f) );
+    return _fh_to_int(f);
+}
+
+#undef accept
+int  adb_socket_accept(int  serverfd, struct sockaddr*  addr, socklen_t  *addrlen)
+{
+    FH   serverfh = _fh_from_int(serverfd);
+    FH   fh;
+
+    if ( !serverfh || serverfh->clazz != &_fh_socket_class ) {
+        D( "adb_socket_accept: invalid fd %d\n", serverfd );
+        return -1;
+    }
+
+    fh = _fh_alloc( &_fh_socket_class );
+    if (!fh) {
+        D( "adb_socket_accept: not enough memory to allocate accepted socket descriptor\n" );
+        return -1;
+    }
+
+    fh->fh_socket = accept( serverfh->fh_socket, addr, addrlen );
+    if (fh->fh_socket == INVALID_SOCKET) {
+        _fh_close( fh );
+        D( "adb_socket_accept: accept on fd %d return error %ld\n", serverfd, GetLastError() );
+        return -1;
+    }
+
+    snprintf( fh->name, sizeof(fh->name), "%d(accept:%s)", _fh_to_int(fh), serverfh->name );
+    D( "adb_socket_accept on fd %d returns fd %d\n", serverfd, _fh_to_int(fh) );
+    return  _fh_to_int(fh);
+}
+
+
+void  disable_tcp_nagle(int fd)
+{
+    FH   fh = _fh_from_int(fd);
+    int  on = 1;
+
+    if ( !fh || fh->clazz != &_fh_socket_class )
+        return;
+
+    setsockopt( fh->fh_socket, IPPROTO_TCP, TCP_NODELAY, (const char*)&on, sizeof(on) );
+}
+
+/**************************************************************************/
+/**************************************************************************/
+/*****                                                                *****/
+/*****    emulated socketpairs                                       *****/
+/*****                                                                *****/
+/**************************************************************************/
+/**************************************************************************/
+
+/* we implement socketpairs directly in use space for the following reasons:
+ *   - it avoids copying data from/to the Nt kernel
+ *   - it allows us to implement fdevent hooks easily and cheaply, something
+ *     that is not possible with standard Win32 pipes !!
+ *
+ * basically, we use two circular buffers, each one corresponding to a given
+ * direction.
+ *
+ * each buffer is implemented as two regions:
+ *
+ *   region A which is (a_start,a_end)
+ *   region B which is (0, b_end)  with b_end <= a_start
+ *
+ * an empty buffer has:  a_start = a_end = b_end = 0
+ *
+ * a_start is the pointer where we start reading data
+ * a_end is the pointer where we start writing data, unless it is BUFFER_SIZE,
+ * then you start writing at b_end
+ *
+ * the buffer is full when  b_end == a_start && a_end == BUFFER_SIZE
+ *
+ * there is room when b_end < a_start || a_end < BUFER_SIZE
+ *
+ * when reading, a_start is incremented, it a_start meets a_end, then
+ * we do:  a_start = 0, a_end = b_end, b_end = 0, and keep going on..
+ */
+
+#define  BIP_BUFFER_SIZE   4096
+
+#if 0
+#include <stdio.h>
+#  define  BIPD(x)      D x
+#  define  BIPDUMP   bip_dump_hex
+
+static void  bip_dump_hex( const unsigned char*  ptr, size_t  len )
+{
+    int  nn, len2 = len;
+
+    if (len2 > 8) len2 = 8;
+
+    for (nn = 0; nn < len2; nn++)
+        printf("%02x", ptr[nn]);
+    printf("  ");
+
+    for (nn = 0; nn < len2; nn++) {
+        int  c = ptr[nn];
+        if (c < 32 || c > 127)
+            c = '.';
+        printf("%c", c);
+    }
+    printf("\n");
+    fflush(stdout);
+}
+
+#else
+#  define  BIPD(x)        do {} while (0)
+#  define  BIPDUMP(p,l)   BIPD(p)
+#endif
+
+typedef struct BipBufferRec_
+{
+    int                a_start;
+    int                a_end;
+    int                b_end;
+    int                fdin;
+    int                fdout;
+    int                closed;
+    int                can_write;  /* boolean */
+    HANDLE             evt_write;  /* event signaled when one can write to a buffer  */
+    int                can_read;   /* boolean */
+    HANDLE             evt_read;   /* event signaled when one can read from a buffer */
+    CRITICAL_SECTION  lock;
+    unsigned char      buff[ BIP_BUFFER_SIZE ];
+
+} BipBufferRec, *BipBuffer;
+
+static void
+bip_buffer_init( BipBuffer  buffer )
+{
+    D( "bit_buffer_init %p\n", buffer );
+    buffer->a_start   = 0;
+    buffer->a_end     = 0;
+    buffer->b_end     = 0;
+    buffer->can_write = 1;
+    buffer->can_read  = 0;
+    buffer->fdin      = 0;
+    buffer->fdout     = 0;
+    buffer->closed    = 0;
+    buffer->evt_write = CreateEvent( NULL, TRUE, TRUE, NULL );
+    buffer->evt_read  = CreateEvent( NULL, TRUE, FALSE, NULL );
+    InitializeCriticalSection( &buffer->lock );
+}
+
+static void
+bip_buffer_close( BipBuffer  bip )
+{
+    bip->closed = 1;
+
+    if (!bip->can_read) {
+        SetEvent( bip->evt_read );
+    }
+    if (!bip->can_write) {
+        SetEvent( bip->evt_write );
+    }
+}
+
+static void
+bip_buffer_done( BipBuffer  bip )
+{
+    BIPD(( "bip_buffer_done: %d->%d\n", bip->fdin, bip->fdout ));
+    CloseHandle( bip->evt_read );
+    CloseHandle( bip->evt_write );
+    DeleteCriticalSection( &bip->lock );
+}
+
+static int
+bip_buffer_write( BipBuffer  bip, const void* src, int  len )
+{
+    int  avail, count = 0;
+
+    if (len <= 0)
+        return 0;
+
+    BIPD(( "bip_buffer_write: enter %d->%d len %d\n", bip->fdin, bip->fdout, len ));
+    BIPDUMP( src, len );
+
+    EnterCriticalSection( &bip->lock );
+
+    while (!bip->can_write) {
+        int  ret;
+        LeaveCriticalSection( &bip->lock );
+
+        if (bip->closed) {
+            errno = EPIPE;
+            return -1;
+        }
+        /* spinlocking here is probably unfair, but let's live with it */
+        ret = WaitForSingleObject( bip->evt_write, INFINITE );
+        if (ret != WAIT_OBJECT_0) {  /* buffer probably closed */
+            D( "bip_buffer_write: error %d->%d WaitForSingleObject returned %d, error %ld\n", bip->fdin, bip->fdout, ret, GetLastError() );
+            return 0;
+        }
+        if (bip->closed) {
+            errno = EPIPE;
+            return -1;
+        }
+        EnterCriticalSection( &bip->lock );
+    }
+
+    BIPD(( "bip_buffer_write: exec %d->%d len %d\n", bip->fdin, bip->fdout, len ));
+
+    avail = BIP_BUFFER_SIZE - bip->a_end;
+    if (avail > 0)
+    {
+        /* we can append to region A */
+        if (avail > len)
+            avail = len;
+
+        memcpy( bip->buff + bip->a_end, src, avail );
+        src   = (const char *)src + avail;
+        count += avail;
+        len   -= avail;
+
+        bip->a_end += avail;
+        if (bip->a_end == BIP_BUFFER_SIZE && bip->a_start == 0) {
+            bip->can_write = 0;
+            ResetEvent( bip->evt_write );
+            goto Exit;
+        }
+    }
+
+    if (len == 0)
+        goto Exit;
+
+    avail = bip->a_start - bip->b_end;
+    assert( avail > 0 );  /* since can_write is TRUE */
+
+    if (avail > len)
+        avail = len;
+
+    memcpy( bip->buff + bip->b_end, src, avail );
+    count += avail;
+    bip->b_end += avail;
+
+    if (bip->b_end == bip->a_start) {
+        bip->can_write = 0;
+        ResetEvent( bip->evt_write );
+    }
+
+Exit:
+    assert( count > 0 );
+
+    if ( !bip->can_read ) {
+        bip->can_read = 1;
+        SetEvent( bip->evt_read );
+    }
+
+    BIPD(( "bip_buffer_write: exit %d->%d count %d (as=%d ae=%d be=%d cw=%d cr=%d\n",
+            bip->fdin, bip->fdout, count, bip->a_start, bip->a_end, bip->b_end, bip->can_write, bip->can_read ));
+    LeaveCriticalSection( &bip->lock );
+
+    return count;
+ }
+
+static int
+bip_buffer_read( BipBuffer  bip, void*  dst, int  len )
+{
+    int  avail, count = 0;
+
+    if (len <= 0)
+        return 0;
+
+    BIPD(( "bip_buffer_read: enter %d->%d len %d\n", bip->fdin, bip->fdout, len ));
+
+    EnterCriticalSection( &bip->lock );
+    while ( !bip->can_read )
+    {
+#if 0
+        LeaveCriticalSection( &bip->lock );
+        errno = EAGAIN;
+        return -1;
+#else
+        int  ret;
+        LeaveCriticalSection( &bip->lock );
+
+        if (bip->closed) {
+            errno = EPIPE;
+            return -1;
+        }
+
+        ret = WaitForSingleObject( bip->evt_read, INFINITE );
+        if (ret != WAIT_OBJECT_0) { /* probably closed buffer */
+            D( "bip_buffer_read: error %d->%d WaitForSingleObject returned %d, error %ld\n", bip->fdin, bip->fdout, ret, GetLastError());
+            return 0;
+        }
+        if (bip->closed) {
+            errno = EPIPE;
+            return -1;
+        }
+        EnterCriticalSection( &bip->lock );
+#endif
+    }
+
+    BIPD(( "bip_buffer_read: exec %d->%d len %d\n", bip->fdin, bip->fdout, len ));
+
+    avail = bip->a_end - bip->a_start;
+    assert( avail > 0 );  /* since can_read is TRUE */
+
+    if (avail > len)
+        avail = len;
+
+    memcpy( dst, bip->buff + bip->a_start, avail );
+    dst   = (char *)dst + avail;
+    count += avail;
+    len   -= avail;
+
+    bip->a_start += avail;
+    if (bip->a_start < bip->a_end)
+        goto Exit;
+
+    bip->a_start = 0;
+    bip->a_end   = bip->b_end;
+    bip->b_end   = 0;
+
+    avail = bip->a_end;
+    if (avail > 0) {
+        if (avail > len)
+            avail = len;
+        memcpy( dst, bip->buff, avail );
+        count += avail;
+        bip->a_start += avail;
+
+        if ( bip->a_start < bip->a_end )
+            goto Exit;
+
+        bip->a_start = bip->a_end = 0;
+    }
+
+    bip->can_read = 0;
+    ResetEvent( bip->evt_read );
+
+Exit:
+    assert( count > 0 );
+
+    if (!bip->can_write ) {
+        bip->can_write = 1;
+        SetEvent( bip->evt_write );
+    }
+
+    BIPDUMP( (const unsigned char*)dst - count, count );
+    BIPD(( "bip_buffer_read: exit %d->%d count %d (as=%d ae=%d be=%d cw=%d cr=%d\n",
+            bip->fdin, bip->fdout, count, bip->a_start, bip->a_end, bip->b_end, bip->can_write, bip->can_read ));
+    LeaveCriticalSection( &bip->lock );
+
+    return count;
+}
+
+typedef struct SocketPairRec_
+{
+    BipBufferRec  a2b_bip;
+    BipBufferRec  b2a_bip;
+    FH            a_fd;
+    int           used;
+
+} SocketPairRec;
+
+void _fh_socketpair_init( FH  f )
+{
+    f->fh_pair = NULL;
+}
+
+static int
+_fh_socketpair_close( FH  f )
+{
+    if ( f->fh_pair ) {
+        SocketPair  pair = f->fh_pair;
+
+        if ( f == pair->a_fd ) {
+            pair->a_fd = NULL;
+        }
+
+        bip_buffer_close( &pair->b2a_bip );
+        bip_buffer_close( &pair->a2b_bip );
+
+        if ( --pair->used == 0 ) {
+            bip_buffer_done( &pair->b2a_bip );
+            bip_buffer_done( &pair->a2b_bip );
+            free( pair );
+        }
+        f->fh_pair = NULL;
+    }
+    return 0;
+}
+
+static int
+_fh_socketpair_lseek( FH  f, int pos, int  origin )
+{
+    errno = ESPIPE;
+    return -1;
+}
+
+static int
+_fh_socketpair_read( FH  f, void* buf, int  len )
+{
+    SocketPair  pair = f->fh_pair;
+    BipBuffer   bip;
+
+    if (!pair)
+        return -1;
+
+    if ( f == pair->a_fd )
+        bip = &pair->b2a_bip;
+    else
+        bip = &pair->a2b_bip;
+
+    return bip_buffer_read( bip, buf, len );
+}
+
+static int
+_fh_socketpair_write( FH  f, const void*  buf, int  len )
+{
+    SocketPair  pair = f->fh_pair;
+    BipBuffer   bip;
+
+    if (!pair)
+        return -1;
+
+    if ( f == pair->a_fd )
+        bip = &pair->a2b_bip;
+    else
+        bip = &pair->b2a_bip;
+
+    return bip_buffer_write( bip, buf, len );
+}
+
+
+static void  _fh_socketpair_hook( FH  f, int  event, EventHook  hook );  /* forward */
+
+static const FHClassRec  _fh_socketpair_class =
+{
+    _fh_socketpair_init,
+    _fh_socketpair_close,
+    _fh_socketpair_lseek,
+    _fh_socketpair_read,
+    _fh_socketpair_write,
+    _fh_socketpair_hook
+};
+
+
+int  adb_socketpair( int  sv[2] )
+{
+    FH          fa, fb;
+    SocketPair  pair;
+
+    fa = _fh_alloc( &_fh_socketpair_class );
+    fb = _fh_alloc( &_fh_socketpair_class );
+
+    if (!fa || !fb)
+        goto Fail;
+
+    pair = malloc( sizeof(*pair) );
+    if (pair == NULL) {
+        D("adb_socketpair: not enough memory to allocate pipes\n" );
+        goto Fail;
+    }
+
+    bip_buffer_init( &pair->a2b_bip );
+    bip_buffer_init( &pair->b2a_bip );
+
+    fa->fh_pair = pair;
+    fb->fh_pair = pair;
+    pair->used  = 2;
+    pair->a_fd  = fa;
+
+    sv[0] = _fh_to_int(fa);
+    sv[1] = _fh_to_int(fb);
+
+    pair->a2b_bip.fdin  = sv[0];
+    pair->a2b_bip.fdout = sv[1];
+    pair->b2a_bip.fdin  = sv[1];
+    pair->b2a_bip.fdout = sv[0];
+
+    snprintf( fa->name, sizeof(fa->name), "%d(pair:%d)", sv[0], sv[1] );
+    snprintf( fb->name, sizeof(fb->name), "%d(pair:%d)", sv[1], sv[0] );
+    D( "adb_socketpair: returns (%d, %d)\n", sv[0], sv[1] );
+    return 0;
+
+Fail:
+    _fh_close(fb);
+    _fh_close(fa);
+    return -1;
+}
+
+/**************************************************************************/
+/**************************************************************************/
+/*****                                                                *****/
+/*****    fdevents emulation                                          *****/
+/*****                                                                *****/
+/*****   this is a very simple implementation, we rely on the fact    *****/
+/*****   that ADB doesn't use FDE_ERROR.                              *****/
+/*****                                                                *****/
+/**************************************************************************/
+/**************************************************************************/
+
+#define FATAL(x...) fatal(__FUNCTION__, x)
+
+#if DEBUG
+static void dump_fde(fdevent *fde, const char *info)
+{
+    fprintf(stderr,"FDE #%03d %c%c%c %s\n", fde->fd,
+            fde->state & FDE_READ ? 'R' : ' ',
+            fde->state & FDE_WRITE ? 'W' : ' ',
+            fde->state & FDE_ERROR ? 'E' : ' ',
+            info);
+}
+#else
+#define dump_fde(fde, info) do { } while(0)
+#endif
+
+#define FDE_EVENTMASK  0x00ff
+#define FDE_STATEMASK  0xff00
+
+#define FDE_ACTIVE     0x0100
+#define FDE_PENDING    0x0200
+#define FDE_CREATED    0x0400
+
+static void fdevent_plist_enqueue(fdevent *node);
+static void fdevent_plist_remove(fdevent *node);
+static fdevent *fdevent_plist_dequeue(void);
+
+static fdevent list_pending = {
+    .next = &list_pending,
+    .prev = &list_pending,
+};
+
+static fdevent **fd_table = 0;
+static int       fd_table_max = 0;
+
+typedef struct EventLooperRec_*  EventLooper;
+
+typedef struct EventHookRec_
+{
+    EventHook    next;
+    FH           fh;
+    HANDLE       h;
+    int          wanted;   /* wanted event flags */
+    int          ready;    /* ready event flags  */
+    void*        aux;
+    void        (*prepare)( EventHook  hook );
+    int         (*start)  ( EventHook  hook );
+    void        (*stop)   ( EventHook  hook );
+    int         (*check)  ( EventHook  hook );
+    int         (*peek)   ( EventHook  hook );
+} EventHookRec;
+
+static EventHook  _free_hooks;
+
+static EventHook
+event_hook_alloc( FH  fh )
+{
+    EventHook  hook = _free_hooks;
+    if (hook != NULL)
+        _free_hooks = hook->next;
+    else {
+        hook = malloc( sizeof(*hook) );
+        if (hook == NULL)
+            fatal( "could not allocate event hook\n" );
+    }
+    hook->next   = NULL;
+    hook->fh     = fh;
+    hook->wanted = 0;
+    hook->ready  = 0;
+    hook->h      = INVALID_HANDLE_VALUE;
+    hook->aux    = NULL;
+
+    hook->prepare = NULL;
+    hook->start   = NULL;
+    hook->stop    = NULL;
+    hook->check   = NULL;
+    hook->peek    = NULL;
+
+    return hook;
+}
+
+static void
+event_hook_free( EventHook  hook )
+{
+    hook->fh     = NULL;
+    hook->wanted = 0;
+    hook->ready  = 0;
+    hook->next   = _free_hooks;
+    _free_hooks  = hook;
+}
+
+
+static void
+event_hook_signal( EventHook  hook )
+{
+    FH        f   = hook->fh;
+    int       fd  = _fh_to_int(f);
+    fdevent*  fde = fd_table[ fd - WIN32_FH_BASE ];
+
+    if (fde != NULL && fde->fd == fd) {
+        if ((fde->state & FDE_PENDING) == 0) {
+            fde->state |= FDE_PENDING;
+            fdevent_plist_enqueue( fde );
+        }
+        fde->events |= hook->wanted;
+    }
+}
+
+
+#define  MAX_LOOPER_HANDLES  WIN32_MAX_FHS
+
+typedef struct EventLooperRec_
+{
+    EventHook    hooks;
+    HANDLE       htab[ MAX_LOOPER_HANDLES ];
+    int          htab_count;
+
+} EventLooperRec;
+
+static EventHook*
+event_looper_find_p( EventLooper  looper, FH  fh )
+{
+    EventHook  *pnode = &looper->hooks;
+    EventHook   node  = *pnode;
+    for (;;) {
+        if ( node == NULL || node->fh == fh )
+            break;
+        pnode = &node->next;
+        node  = *pnode;
+    }
+    return  pnode;
+}
+
+static void
+event_looper_hook( EventLooper  looper, int  fd, int  events )
+{
+    FH          f = _fh_from_int(fd);
+    EventHook  *pnode;
+    EventHook   node;
+
+    if (f == NULL)  /* invalid arg */ {
+        D("event_looper_hook: invalid fd=%d\n", fd);
+        return;
+    }
+
+    pnode = event_looper_find_p( looper, f );
+    node  = *pnode;
+    if ( node == NULL ) {
+        node       = event_hook_alloc( f );
+        node->next = *pnode;
+        *pnode     = node;
+    }
+
+    if ( (node->wanted & events) != events ) {
+        /* this should update start/stop/check/peek */
+        D("event_looper_hook: call hook for %d (new=%x, old=%x)\n",
+           fd, node->wanted, events);
+        f->clazz->_fh_hook( f, events & ~node->wanted, node );
+        node->wanted |= events;
+    } else {
+        D("event_looper_hook: ignoring events %x for %d wanted=%x)\n",
+           events, fd, node->wanted);
+    }
+}
+
+static void
+event_looper_unhook( EventLooper  looper, int  fd, int  events )
+{
+    FH          fh    = _fh_from_int(fd);
+    EventHook  *pnode = event_looper_find_p( looper, fh );
+    EventHook   node  = *pnode;
+
+    if (node != NULL) {
+        int  events2 = events & node->wanted;
+        if ( events2 == 0 ) {
+            D( "event_looper_unhook: events %x not registered for fd %d\n", events, fd );
+            return;
+        }
+        node->wanted &= ~events2;
+        if (!node->wanted) {
+            *pnode = node->next;
+            event_hook_free( node );
+        }
+    }
+}
+
+/*
+ * A fixer for WaitForMultipleObjects on condition that there are more than 64
+ * handles to wait on.
+ *
+ * In cetain cases DDMS may establish more than 64 connections with ADB. For
+ * instance, this may happen if there are more than 64 processes running on a
+ * device, or there are multiple devices connected (including the emulator) with
+ * the combined number of running processes greater than 64. In this case using
+ * WaitForMultipleObjects to wait on connection events simply wouldn't cut,
+ * because of the API limitations (64 handles max). So, we need to provide a way
+ * to scale WaitForMultipleObjects to accept an arbitrary number of handles. The
+ * easiest (and "Microsoft recommended") way to do that would be dividing the
+ * handle array into chunks with the chunk size less than 64, and fire up as many
+ * waiting threads as there are chunks. Then each thread would wait on a chunk of
+ * handles, and will report back to the caller which handle has been set.
+ * Here is the implementation of that algorithm.
+ */
+
+/* Number of handles to wait on in each wating thread. */
+#define WAIT_ALL_CHUNK_SIZE 63
+
+/* Descriptor for a wating thread */
+typedef struct WaitForAllParam {
+    /* A handle to an event to signal when waiting is over. This handle is shared
+     * accross all the waiting threads, so each waiting thread knows when any
+     * other thread has exited, so it can exit too. */
+    HANDLE          main_event;
+    /* Upon exit from a waiting thread contains the index of the handle that has
+     * been signaled. The index is an absolute index of the signaled handle in
+     * the original array. This pointer is shared accross all the waiting threads
+     * and it's not guaranteed (due to a race condition) that when all the
+     * waiting threads exit, the value contained here would indicate the first
+     * handle that was signaled. This is fine, because the caller cares only
+     * about any handle being signaled. It doesn't care about the order, nor
+     * about the whole list of handles that were signaled. */
+    LONG volatile   *signaled_index;
+    /* Array of handles to wait on in a waiting thread. */
+    HANDLE*         handles;
+    /* Number of handles in 'handles' array to wait on. */
+    int             handles_count;
+    /* Index inside the main array of the first handle in the 'handles' array. */
+    int             first_handle_index;
+    /* Waiting thread handle. */
+    HANDLE          thread;
+} WaitForAllParam;
+
+/* Waiting thread routine. */
+static unsigned __stdcall
+_in_waiter_thread(void*  arg)
+{
+    HANDLE wait_on[WAIT_ALL_CHUNK_SIZE + 1];
+    int res;
+    WaitForAllParam* const param = (WaitForAllParam*)arg;
+
+    /* We have to wait on the main_event in order to be notified when any of the
+     * sibling threads is exiting. */
+    wait_on[0] = param->main_event;
+    /* The rest of the handles go behind the main event handle. */
+    memcpy(wait_on + 1, param->handles, param->handles_count * sizeof(HANDLE));
+
+    res = WaitForMultipleObjects(param->handles_count + 1, wait_on, FALSE, INFINITE);
+    if (res > 0 && res < (param->handles_count + 1)) {
+        /* One of the original handles got signaled. Save its absolute index into
+         * the output variable. */
+        InterlockedCompareExchange(param->signaled_index,
+                                   res - 1L + param->first_handle_index, -1L);
+    }
+
+    /* Notify the caller (and the siblings) that the wait is over. */
+    SetEvent(param->main_event);
+
+    _endthreadex(0);
+    return 0;
+}
+
+/* WaitForMultipeObjects fixer routine.
+ * Param:
+ *  handles Array of handles to wait on.
+ *  handles_count Number of handles in the array.
+ * Return:
+ *  (>= 0 && < handles_count) - Index of the signaled handle in the array, or
+ *  WAIT_FAILED on an error.
+ */
+static int
+_wait_for_all(HANDLE* handles, int handles_count)
+{
+    WaitForAllParam* threads;
+    HANDLE main_event;
+    int chunks, chunk, remains;
+
+    /* This variable is going to be accessed by several threads at the same time,
+     * this is bound to fail randomly when the core is run on multi-core machines.
+     * To solve this, we need to do the following (1 _and_ 2):
+     * 1. Use the "volatile" qualifier to ensure the compiler doesn't optimize
+     *    out the reads/writes in this function unexpectedly.
+     * 2. Ensure correct memory ordering. The "simple" way to do that is to wrap
+     *    all accesses inside a critical section. But we can also use
+     *    InterlockedCompareExchange() which always provide a full memory barrier
+     *    on Win32.
+     */
+    volatile LONG sig_index = -1;
+
+    /* Calculate number of chunks, and allocate thread param array. */
+    chunks = handles_count / WAIT_ALL_CHUNK_SIZE;
+    remains = handles_count % WAIT_ALL_CHUNK_SIZE;
+    threads = (WaitForAllParam*)malloc((chunks + (remains ? 1 : 0)) *
+                                        sizeof(WaitForAllParam));
+    if (threads == NULL) {
+        D("Unable to allocate thread array for %d handles.", handles_count);
+        return (int)WAIT_FAILED;
+    }
+
+    /* Create main event to wait on for all waiting threads. This is a "manualy
+     * reset" event that will remain set once it was set. */
+    main_event = CreateEvent(NULL, TRUE, FALSE, NULL);
+    if (main_event == NULL) {
+        D("Unable to create main event. Error: %d", GetLastError());
+        free(threads);
+        return (int)WAIT_FAILED;
+    }
+
+    /*
+     * Initialize waiting thread parameters.
+     */
+
+    for (chunk = 0; chunk < chunks; chunk++) {
+        threads[chunk].main_event = main_event;
+        threads[chunk].signaled_index = &sig_index;
+        threads[chunk].first_handle_index = WAIT_ALL_CHUNK_SIZE * chunk;
+        threads[chunk].handles = handles + threads[chunk].first_handle_index;
+        threads[chunk].handles_count = WAIT_ALL_CHUNK_SIZE;
+    }
+    if (remains) {
+        threads[chunk].main_event = main_event;
+        threads[chunk].signaled_index = &sig_index;
+        threads[chunk].first_handle_index = WAIT_ALL_CHUNK_SIZE * chunk;
+        threads[chunk].handles = handles + threads[chunk].first_handle_index;
+        threads[chunk].handles_count = remains;
+        chunks++;
+    }
+
+    /* Start the waiting threads. */
+    for (chunk = 0; chunk < chunks; chunk++) {
+        /* Note that using adb_thread_create is not appropriate here, since we
+         * need a handle to wait on for thread termination. */
+        threads[chunk].thread = (HANDLE)_beginthreadex(NULL, 0, _in_waiter_thread,
+                                                       &threads[chunk], 0, NULL);
+        if (threads[chunk].thread == NULL) {
+            /* Unable to create a waiter thread. Collapse. */
+            D("Unable to create a waiting thread %d of %d. errno=%d",
+              chunk, chunks, errno);
+            chunks = chunk;
+            SetEvent(main_event);
+            break;
+        }
+    }
+
+    /* Wait on any of the threads to get signaled. */
+    WaitForSingleObject(main_event, INFINITE);
+
+    /* Wait on all the waiting threads to exit. */
+    for (chunk = 0; chunk < chunks; chunk++) {
+        WaitForSingleObject(threads[chunk].thread, INFINITE);
+        CloseHandle(threads[chunk].thread);
+    }
+
+    CloseHandle(main_event);
+    free(threads);
+
+
+    const int ret = (int)InterlockedCompareExchange(&sig_index, -1, -1);
+    return (ret >= 0) ? ret : (int)WAIT_FAILED;
+}
+
+static EventLooperRec  win32_looper;
+
+static void fdevent_init(void)
+{
+    win32_looper.htab_count = 0;
+    win32_looper.hooks      = NULL;
+}
+
+static void fdevent_connect(fdevent *fde)
+{
+    EventLooper  looper = &win32_looper;
+    int          events = fde->state & FDE_EVENTMASK;
+
+    if (events != 0)
+        event_looper_hook( looper, fde->fd, events );
+}
+
+static void fdevent_disconnect(fdevent *fde)
+{
+    EventLooper  looper = &win32_looper;
+    int          events = fde->state & FDE_EVENTMASK;
+
+    if (events != 0)
+        event_looper_unhook( looper, fde->fd, events );
+}
+
+static void fdevent_update(fdevent *fde, unsigned events)
+{
+    EventLooper  looper  = &win32_looper;
+    unsigned     events0 = fde->state & FDE_EVENTMASK;
+
+    if (events != events0) {
+        int  removes = events0 & ~events;
+        int  adds    = events  & ~events0;
+        if (removes) {
+            D("fdevent_update: remove %x from %d\n", removes, fde->fd);
+            event_looper_unhook( looper, fde->fd, removes );
+        }
+        if (adds) {
+            D("fdevent_update: add %x to %d\n", adds, fde->fd);
+            event_looper_hook  ( looper, fde->fd, adds );
+        }
+    }
+}
+
+static void fdevent_process()
+{
+    EventLooper  looper = &win32_looper;
+    EventHook    hook;
+    int          gotone = 0;
+
+    /* if we have at least one ready hook, execute it/them */
+    for (hook = looper->hooks; hook; hook = hook->next) {
+        hook->ready = 0;
+        if (hook->prepare) {
+            hook->prepare(hook);
+            if (hook->ready != 0) {
+                event_hook_signal( hook );
+                gotone = 1;
+            }
+        }
+    }
+
+    /* nothing's ready yet, so wait for something to happen */
+    if (!gotone)
+    {
+        looper->htab_count = 0;
+
+        for (hook = looper->hooks; hook; hook = hook->next)
+        {
+            if (hook->start && !hook->start(hook)) {
+                D( "fdevent_process: error when starting a hook\n" );
+                return;
+            }
+            if (hook->h != INVALID_HANDLE_VALUE) {
+                int  nn;
+
+                for (nn = 0; nn < looper->htab_count; nn++)
+                {
+                    if ( looper->htab[nn] == hook->h )
+                        goto DontAdd;
+                }
+                looper->htab[ looper->htab_count++ ] = hook->h;
+            DontAdd:
+                ;
+            }
+        }
+
+        if (looper->htab_count == 0) {
+            D( "fdevent_process: nothing to wait for !!\n" );
+            return;
+        }
+
+        do
+        {
+            int   wait_ret;
+
+            D( "adb_win32: waiting for %d events\n", looper->htab_count );
+            if (looper->htab_count > MAXIMUM_WAIT_OBJECTS) {
+                D("handle count %d exceeds MAXIMUM_WAIT_OBJECTS.\n", looper->htab_count);
+                wait_ret = _wait_for_all(looper->htab, looper->htab_count);
+            } else {
+                wait_ret = WaitForMultipleObjects( looper->htab_count, looper->htab, FALSE, INFINITE );
+            }
+            if (wait_ret == (int)WAIT_FAILED) {
+                D( "adb_win32: wait failed, error %ld\n", GetLastError() );
+            } else {
+                D( "adb_win32: got one (index %d)\n", wait_ret );
+
+                /* according to Cygwin, some objects like consoles wake up on "inappropriate" events
+                 * like mouse movements. we need to filter these with the "check" function
+                 */
+                if ((unsigned)wait_ret < (unsigned)looper->htab_count)
+                {
+                    for (hook = looper->hooks; hook; hook = hook->next)
+                    {
+                        if ( looper->htab[wait_ret] == hook->h       &&
+                         (!hook->check || hook->check(hook)) )
+                        {
+                            D( "adb_win32: signaling %s for %x\n", hook->fh->name, hook->ready );
+                            event_hook_signal( hook );
+                            gotone = 1;
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+        while (!gotone);
+
+        for (hook = looper->hooks; hook; hook = hook->next) {
+            if (hook->stop)
+                hook->stop( hook );
+        }
+    }
+
+    for (hook = looper->hooks; hook; hook = hook->next) {
+        if (hook->peek && hook->peek(hook))
+                event_hook_signal( hook );
+    }
+}
+
+
+static void fdevent_register(fdevent *fde)
+{
+    int  fd = fde->fd - WIN32_FH_BASE;
+
+    if(fd < 0) {
+        FATAL("bogus negative fd (%d)\n", fde->fd);
+    }
+
+    if(fd >= fd_table_max) {
+        int oldmax = fd_table_max;
+        if(fde->fd > 32000) {
+            FATAL("bogus huuuuge fd (%d)\n", fde->fd);
+        }
+        if(fd_table_max == 0) {
+            fdevent_init();
+            fd_table_max = 256;
+        }
+        while(fd_table_max <= fd) {
+            fd_table_max *= 2;
+        }
+        fd_table = realloc(fd_table, sizeof(fdevent*) * fd_table_max);
+        if(fd_table == 0) {
+            FATAL("could not expand fd_table to %d entries\n", fd_table_max);
+        }
+        memset(fd_table + oldmax, 0, sizeof(int) * (fd_table_max - oldmax));
+    }
+
+    fd_table[fd] = fde;
+}
+
+static void fdevent_unregister(fdevent *fde)
+{
+    int  fd = fde->fd - WIN32_FH_BASE;
+
+    if((fd < 0) || (fd >= fd_table_max)) {
+        FATAL("fd out of range (%d)\n", fde->fd);
+    }
+
+    if(fd_table[fd] != fde) {
+        FATAL("fd_table out of sync");
+    }
+
+    fd_table[fd] = 0;
+
+    if(!(fde->state & FDE_DONT_CLOSE)) {
+        dump_fde(fde, "close");
+        adb_close(fde->fd);
+    }
+}
+
+static void fdevent_plist_enqueue(fdevent *node)
+{
+    fdevent *list = &list_pending;
+
+    node->next = list;
+    node->prev = list->prev;
+    node->prev->next = node;
+    list->prev = node;
+}
+
+static void fdevent_plist_remove(fdevent *node)
+{
+    node->prev->next = node->next;
+    node->next->prev = node->prev;
+    node->next = 0;
+    node->prev = 0;
+}
+
+static fdevent *fdevent_plist_dequeue(void)
+{
+    fdevent *list = &list_pending;
+    fdevent *node = list->next;
+
+    if(node == list) return 0;
+
+    list->next = node->next;
+    list->next->prev = list;
+    node->next = 0;
+    node->prev = 0;
+
+    return node;
+}
+
+fdevent *fdevent_create(int fd, fd_func func, void *arg)
+{
+    fdevent *fde = (fdevent*) malloc(sizeof(fdevent));
+    if(fde == 0) return 0;
+    fdevent_install(fde, fd, func, arg);
+    fde->state |= FDE_CREATED;
+    return fde;
+}
+
+void fdevent_destroy(fdevent *fde)
+{
+    if(fde == 0) return;
+    if(!(fde->state & FDE_CREATED)) {
+        FATAL("fde %p not created by fdevent_create()\n", fde);
+    }
+    fdevent_remove(fde);
+}
+
+void fdevent_install(fdevent *fde, int fd, fd_func func, void *arg)
+{
+    memset(fde, 0, sizeof(fdevent));
+    fde->state = FDE_ACTIVE;
+    fde->fd = fd;
+    fde->func = func;
+    fde->arg = arg;
+
+    fdevent_register(fde);
+    dump_fde(fde, "connect");
+    fdevent_connect(fde);
+    fde->state |= FDE_ACTIVE;
+}
+
+void fdevent_remove(fdevent *fde)
+{
+    if(fde->state & FDE_PENDING) {
+        fdevent_plist_remove(fde);
+    }
+
+    if(fde->state & FDE_ACTIVE) {
+        fdevent_disconnect(fde);
+        dump_fde(fde, "disconnect");
+        fdevent_unregister(fde);
+    }
+
+    fde->state = 0;
+    fde->events = 0;
+}
+
+
+void fdevent_set(fdevent *fde, unsigned events)
+{
+    events &= FDE_EVENTMASK;
+
+    if((fde->state & FDE_EVENTMASK) == (int)events) return;
+
+    if(fde->state & FDE_ACTIVE) {
+        fdevent_update(fde, events);
+        dump_fde(fde, "update");
+    }
+
+    fde->state = (fde->state & FDE_STATEMASK) | events;
+
+    if(fde->state & FDE_PENDING) {
+            /* if we're pending, make sure
+            ** we don't signal an event that
+            ** is no longer wanted.
+            */
+        fde->events &= (~events);
+        if(fde->events == 0) {
+            fdevent_plist_remove(fde);
+            fde->state &= (~FDE_PENDING);
+        }
+    }
+}
+
+void fdevent_add(fdevent *fde, unsigned events)
+{
+    fdevent_set(
+        fde, (fde->state & FDE_EVENTMASK) | (events & FDE_EVENTMASK));
+}
+
+void fdevent_del(fdevent *fde, unsigned events)
+{
+    fdevent_set(
+        fde, (fde->state & FDE_EVENTMASK) & (~(events & FDE_EVENTMASK)));
+}
+
+void fdevent_loop()
+{
+    fdevent *fde;
+
+    for(;;) {
+#if DEBUG
+        fprintf(stderr,"--- ---- waiting for events\n");
+#endif
+        fdevent_process();
+
+        while((fde = fdevent_plist_dequeue())) {
+            unsigned events = fde->events;
+            fde->events = 0;
+            fde->state &= (~FDE_PENDING);
+            dump_fde(fde, "callback");
+            fde->func(fde->fd, events, fde->arg);
+        }
+    }
+}
+
+/**  FILE EVENT HOOKS
+ **/
+
+static void  _event_file_prepare( EventHook  hook )
+{
+    if (hook->wanted & (FDE_READ|FDE_WRITE)) {
+        /* we can always read/write */
+        hook->ready |= hook->wanted & (FDE_READ|FDE_WRITE);
+    }
+}
+
+static int  _event_file_peek( EventHook  hook )
+{
+    return (hook->wanted & (FDE_READ|FDE_WRITE));
+}
+
+static void  _fh_file_hook( FH  f, int  events, EventHook  hook )
+{
+    hook->h       = f->fh_handle;
+    hook->prepare = _event_file_prepare;
+    hook->peek    = _event_file_peek;
+}
+
+/** SOCKET EVENT HOOKS
+ **/
+
+static void  _event_socket_verify( EventHook  hook, WSANETWORKEVENTS*  evts )
+{
+    if ( evts->lNetworkEvents & (FD_READ|FD_ACCEPT|FD_CLOSE) ) {
+        if (hook->wanted & FDE_READ)
+            hook->ready |= FDE_READ;
+        if ((evts->iErrorCode[FD_READ] != 0) && hook->wanted & FDE_ERROR)
+            hook->ready |= FDE_ERROR;
+    }
+    if ( evts->lNetworkEvents & (FD_WRITE|FD_CONNECT|FD_CLOSE) ) {
+        if (hook->wanted & FDE_WRITE)
+            hook->ready |= FDE_WRITE;
+        if ((evts->iErrorCode[FD_WRITE] != 0) && hook->wanted & FDE_ERROR)
+            hook->ready |= FDE_ERROR;
+    }
+    if ( evts->lNetworkEvents & FD_OOB ) {
+        if (hook->wanted & FDE_ERROR)
+            hook->ready |= FDE_ERROR;
+    }
+}
+
+static void  _event_socket_prepare( EventHook  hook )
+{
+    WSANETWORKEVENTS  evts;
+
+    /* look if some of the events we want already happened ? */
+    if (!WSAEnumNetworkEvents( hook->fh->fh_socket, NULL, &evts ))
+        _event_socket_verify( hook, &evts );
+}
+
+static int  _socket_wanted_to_flags( int  wanted )
+{
+    int  flags = 0;
+    if (wanted & FDE_READ)
+        flags |= FD_READ | FD_ACCEPT | FD_CLOSE;
+
+    if (wanted & FDE_WRITE)
+        flags |= FD_WRITE | FD_CONNECT | FD_CLOSE;
+
+    if (wanted & FDE_ERROR)
+        flags |= FD_OOB;
+
+    return flags;
+}
+
+static int _event_socket_start( EventHook  hook )
+{
+    /* create an event which we're going to wait for */
+    FH    fh    = hook->fh;
+    long  flags = _socket_wanted_to_flags( hook->wanted );
+
+    hook->h = fh->event;
+    if (hook->h == INVALID_HANDLE_VALUE) {
+        D( "_event_socket_start: no event for %s\n", fh->name );
+        return 0;
+    }
+
+    if ( flags != fh->mask ) {
+        D( "_event_socket_start: hooking %s for %x (flags %ld)\n", hook->fh->name, hook->wanted, flags );
+        if ( WSAEventSelect( fh->fh_socket, hook->h, flags ) ) {
+            D( "_event_socket_start: WSAEventSelect() for %s failed, error %d\n", hook->fh->name, WSAGetLastError() );
+            CloseHandle( hook->h );
+            hook->h = INVALID_HANDLE_VALUE;
+            exit(1);
+            return 0;
+        }
+        fh->mask = flags;
+    }
+    return 1;
+}
+
+static void _event_socket_stop( EventHook  hook )
+{
+    hook->h = INVALID_HANDLE_VALUE;
+}
+
+static int  _event_socket_check( EventHook  hook )
+{
+    int               result = 0;
+    FH                fh = hook->fh;
+    WSANETWORKEVENTS  evts;
+
+    if (!WSAEnumNetworkEvents( fh->fh_socket, hook->h, &evts ) ) {
+        _event_socket_verify( hook, &evts );
+        result = (hook->ready != 0);
+        if (result) {
+            ResetEvent( hook->h );
+        }
+    }
+    D( "_event_socket_check %s returns %d\n", fh->name, result );
+    return  result;
+}
+
+static int  _event_socket_peek( EventHook  hook )
+{
+    WSANETWORKEVENTS  evts;
+    FH                fh = hook->fh;
+
+    /* look if some of the events we want already happened ? */
+    if (!WSAEnumNetworkEvents( fh->fh_socket, NULL, &evts )) {
+        _event_socket_verify( hook, &evts );
+        if (hook->ready)
+            ResetEvent( hook->h );
+    }
+
+    return hook->ready != 0;
+}
+
+
+
+static void  _fh_socket_hook( FH  f, int  events, EventHook  hook )
+{
+    hook->prepare = _event_socket_prepare;
+    hook->start   = _event_socket_start;
+    hook->stop    = _event_socket_stop;
+    hook->check   = _event_socket_check;
+    hook->peek    = _event_socket_peek;
+
+    _event_socket_start( hook );
+}
+
+/** SOCKETPAIR EVENT HOOKS
+ **/
+
+static void  _event_socketpair_prepare( EventHook  hook )
+{
+    FH          fh   = hook->fh;
+    SocketPair  pair = fh->fh_pair;
+    BipBuffer   rbip = (pair->a_fd == fh) ? &pair->b2a_bip : &pair->a2b_bip;
+    BipBuffer   wbip = (pair->a_fd == fh) ? &pair->a2b_bip : &pair->b2a_bip;
+
+    if (hook->wanted & FDE_READ && rbip->can_read)
+        hook->ready |= FDE_READ;
+
+    if (hook->wanted & FDE_WRITE && wbip->can_write)
+        hook->ready |= FDE_WRITE;
+ }
+
+ static int  _event_socketpair_start( EventHook  hook )
+ {
+    FH          fh   = hook->fh;
+    SocketPair  pair = fh->fh_pair;
+    BipBuffer   rbip = (pair->a_fd == fh) ? &pair->b2a_bip : &pair->a2b_bip;
+    BipBuffer   wbip = (pair->a_fd == fh) ? &pair->a2b_bip : &pair->b2a_bip;
+
+    if (hook->wanted == FDE_READ)
+        hook->h = rbip->evt_read;
+
+    else if (hook->wanted == FDE_WRITE)
+        hook->h = wbip->evt_write;
+
+    else {
+        D("_event_socketpair_start: can't handle FDE_READ+FDE_WRITE\n" );
+        return 0;
+    }
+    D( "_event_socketpair_start: hook %s for %x wanted=%x\n",
+       hook->fh->name, _fh_to_int(fh), hook->wanted);
+    return 1;
+}
+
+static int  _event_socketpair_peek( EventHook  hook )
+{
+    _event_socketpair_prepare( hook );
+    return hook->ready != 0;
+}
+
+static void  _fh_socketpair_hook( FH  fh, int  events, EventHook  hook )
+{
+    hook->prepare = _event_socketpair_prepare;
+    hook->start   = _event_socketpair_start;
+    hook->peek    = _event_socketpair_peek;
+}
+
+
+void
+adb_sysdeps_init( void )
+{
+#define  ADB_MUTEX(x)  InitializeCriticalSection( & x );
+#include "mutex_list.h"
+    InitializeCriticalSection( &_win32_lock );
+}
+
+/* Windows doesn't have strtok_r.  Use the one from bionic. */
+
+/*
+ * Copyright (c) 1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+char *
+adb_strtok_r(char *s, const char *delim, char **last)
+{
+	char *spanp;
+	int c, sc;
+	char *tok;
+
+
+	if (s == NULL && (s = *last) == NULL)
+		return (NULL);
+
+	/*
+	 * Skip (span) leading delimiters (s += strspn(s, delim), sort of).
+	 */
+cont:
+	c = *s++;
+	for (spanp = (char *)delim; (sc = *spanp++) != 0;) {
+		if (c == sc)
+			goto cont;
+	}
+
+	if (c == 0) {		/* no non-delimiter characters */
+		*last = NULL;
+		return (NULL);
+	}
+	tok = s - 1;
+
+	/*
+	 * Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
+	 * Note that delim must have one NUL; we stop if we see that, too.
+	 */
+	for (;;) {
+		c = *s++;
+		spanp = (char *)delim;
+		do {
+			if ((sc = *spanp++) == c) {
+				if (c == 0)
+					s = NULL;
+				else
+					s[-1] = 0;
+				*last = s;
+				return (tok);
+			}
+		} while (sc != 0);
+	}
+	/* NOTREACHED */
+}
diff --git a/package/utils/adbd/src/adb/test_track_devices.c b/package/utils/adbd/src/adb/test_track_devices.c
new file mode 100644
index 0000000..77b3ad9
--- /dev/null
+++ b/package/utils/adbd/src/adb/test_track_devices.c
@@ -0,0 +1,97 @@
+/* a simple test program, connects to ADB server, and opens a track-devices session */
+#include <netdb.h>
+#include <sys/socket.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <memory.h>
+
+static void
+panic( const char*  msg )
+{
+    fprintf(stderr, "PANIC: %s: %s\n", msg, strerror(errno));
+    exit(1);
+}
+
+static int
+unix_write( int  fd, const char*  buf, int  len )
+{
+    int  result = 0;
+    while (len > 0) {
+        int  len2 = write(fd, buf, len);
+        if (len2 < 0) {
+            if (errno == EINTR || errno == EAGAIN)
+                continue;
+            return -1;
+        }
+        result += len2;
+        len -= len2;
+        buf += len2;
+    }
+    return  result;
+}
+
+static int
+unix_read( int  fd, char*  buf, int  len )
+{
+    int  result = 0;
+    while (len > 0) {
+        int  len2 = read(fd, buf, len);
+        if (len2 < 0) {
+            if (errno == EINTR || errno == EAGAIN)
+                continue;
+            return -1;
+        }
+        result += len2;
+        len -= len2;
+        buf += len2;
+    }
+    return  result;
+}
+
+
+int  main( void )
+{
+    int                  ret, s;
+    struct sockaddr_in   server;
+    char                 buffer[1024];
+    const char*          request = "host:track-devices";
+    int                  len;
+
+    memset( &server, 0, sizeof(server) );
+    server.sin_family      = AF_INET;
+    server.sin_port        = htons(5037);
+    server.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+
+    s = socket( PF_INET, SOCK_STREAM, 0 );
+    ret = connect( s, (struct sockaddr*) &server, sizeof(server) );
+    if (ret < 0) panic( "could not connect to server" );
+
+    /* send the request */
+    len = snprintf( buffer, sizeof buffer, "%04x%s", strlen(request), request );
+    if (unix_write(s, buffer, len) < 0)
+        panic( "could not send request" );
+
+    /* read the OKAY answer */
+    if (unix_read(s, buffer, 4) != 4)
+        panic( "could not read request" );
+
+    printf( "server answer: %.*s\n", 4, buffer );
+
+    /* now loop */
+    for (;;) {
+        char  head[5] = "0000";
+
+        if (unix_read(s, head, 4) < 0)
+            panic("could not read length");
+
+        if ( sscanf( head, "%04x", &len ) != 1 )
+            panic("could not decode length");
+
+        if (unix_read(s, buffer, len) != len)
+            panic("could not read data");
+
+        printf( "received header %.*s (%d bytes):\n%.*s", 4, head, len, len, buffer );
+    }
+    close(s);
+}
diff --git a/package/utils/adbd/src/adb/test_track_jdwp.c b/package/utils/adbd/src/adb/test_track_jdwp.c
new file mode 100644
index 0000000..8ecc6b8
--- /dev/null
+++ b/package/utils/adbd/src/adb/test_track_jdwp.c
@@ -0,0 +1,97 @@
+/* a simple test program, connects to ADB server, and opens a track-devices session */
+#include <netdb.h>
+#include <sys/socket.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <memory.h>
+
+static void
+panic( const char*  msg )
+{
+    fprintf(stderr, "PANIC: %s: %s\n", msg, strerror(errno));
+    exit(1);
+}
+
+static int
+unix_write( int  fd, const char*  buf, int  len )
+{
+    int  result = 0;
+    while (len > 0) {
+        int  len2 = write(fd, buf, len);
+        if (len2 < 0) {
+            if (errno == EINTR || errno == EAGAIN)
+                continue;
+            return -1;
+        }
+        result += len2;
+        len -= len2;
+        buf += len2;
+    }
+    return  result;
+}
+
+static int
+unix_read( int  fd, char*  buf, int  len )
+{
+    int  result = 0;
+    while (len > 0) {
+        int  len2 = read(fd, buf, len);
+        if (len2 < 0) {
+            if (errno == EINTR || errno == EAGAIN)
+                continue;
+            return -1;
+        }
+        result += len2;
+        len -= len2;
+        buf += len2;
+    }
+    return  result;
+}
+
+
+int  main( void )
+{
+    int                  ret, s;
+    struct sockaddr_in   server;
+    char                 buffer[1024];
+    const char*          request = "track-jdwp";
+    int                  len;
+
+    memset( &server, 0, sizeof(server) );
+    server.sin_family      = AF_INET;
+    server.sin_port        = htons(5037);
+    server.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+
+    s = socket( PF_INET, SOCK_STREAM, 0 );
+    ret = connect( s, (struct sockaddr*) &server, sizeof(server) );
+    if (ret < 0) panic( "could not connect to server" );
+
+    /* send the request */
+    len = snprintf( buffer, sizeof buffer, "%04x%s", strlen(request), request );
+    if (unix_write(s, buffer, len) < 0)
+        panic( "could not send request" );
+
+    /* read the OKAY answer */
+    if (unix_read(s, buffer, 4) != 4)
+        panic( "could not read request" );
+
+    printf( "server answer: %.*s\n", 4, buffer );
+
+    /* now loop */
+    for (;;) {
+        char  head[5] = "0000";
+
+        if (unix_read(s, head, 4) < 0)
+            panic("could not read length");
+
+        if ( sscanf( head, "%04x", &len ) != 1 )
+            panic("could not decode length");
+
+        if (unix_read(s, buffer, len) != len)
+            panic("could not read data");
+
+        printf( "received header %.*s (%d bytes):\n%.*s", 4, head, len, len, buffer );
+    }
+    close(s);
+}
diff --git a/package/utils/adbd/src/adb/transport.c b/package/utils/adbd/src/adb/transport.c
new file mode 100644
index 0000000..38b05d4
--- /dev/null
+++ b/package/utils/adbd/src/adb/transport.c
@@ -0,0 +1,1238 @@
+/*
+ * 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 <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include "sysdeps.h"
+
+#define   TRACE_TAG  TRACE_TRANSPORT
+#include "adb.h"
+
+static void transport_unref(atransport *t);
+
+static atransport transport_list = {
+    .next = &transport_list,
+    .prev = &transport_list,
+};
+
+static atransport pending_list = {
+    .next = &pending_list,
+    .prev = &pending_list,
+};
+
+ADB_MUTEX_DEFINE( transport_lock );
+
+#if ADB_TRACE
+#define MAX_DUMP_HEX_LEN 16
+static void  dump_hex( const unsigned char*  ptr, size_t  len )
+{
+    int  nn, len2 = len;
+    // Build a string instead of logging each character.
+    // MAX chars in 2 digit hex, one space, MAX chars, one '\0'.
+    char buffer[MAX_DUMP_HEX_LEN *2 + 1 + MAX_DUMP_HEX_LEN + 1 ], *pb = buffer;
+
+    if (len2 > MAX_DUMP_HEX_LEN) len2 = MAX_DUMP_HEX_LEN;
+
+    for (nn = 0; nn < len2; nn++) {
+        sprintf(pb, "%02x", ptr[nn]);
+        pb += 2;
+    }
+    sprintf(pb++, " ");
+
+    for (nn = 0; nn < len2; nn++) {
+        int  c = ptr[nn];
+        if (c < 32 || c > 127)
+            c = '.';
+        *pb++ =  c;
+    }
+    *pb++ = '\0';
+    DR("%s\n", buffer);
+}
+#endif
+
+void
+kick_transport(atransport*  t)
+{
+    if (t && !t->kicked)
+    {
+        int  kicked;
+
+        adb_mutex_lock(&transport_lock);
+        kicked = t->kicked;
+        if (!kicked)
+            t->kicked = 1;
+        adb_mutex_unlock(&transport_lock);
+
+        if (!kicked)
+            t->kick(t);
+    }
+}
+
+void
+run_transport_disconnects(atransport*  t)
+{
+    adisconnect*  dis = t->disconnects.next;
+
+    D("%s: run_transport_disconnects\n", t->serial);
+    while (dis != &t->disconnects) {
+        adisconnect*  next = dis->next;
+        dis->func( dis->opaque, t );
+        dis = next;
+    }
+}
+
+#if ADB_TRACE
+static void
+dump_packet(const char* name, const char* func, apacket* p)
+{
+    unsigned  command = p->msg.command;
+    int       len     = p->msg.data_length;
+    char      cmd[9];
+    char      arg0[12], arg1[12];
+    int       n;
+
+    for (n = 0; n < 4; n++) {
+        int  b = (command >> (n*8)) & 255;
+        if (b < 32 || b >= 127)
+            break;
+        cmd[n] = (char)b;
+    }
+    if (n == 4) {
+        cmd[4] = 0;
+    } else {
+        /* There is some non-ASCII name in the command, so dump
+            * the hexadecimal value instead */
+        snprintf(cmd, sizeof cmd, "%08x", command);
+    }
+
+    if (p->msg.arg0 < 256U)
+        snprintf(arg0, sizeof arg0, "%d", p->msg.arg0);
+    else
+        snprintf(arg0, sizeof arg0, "0x%x", p->msg.arg0);
+
+    if (p->msg.arg1 < 256U)
+        snprintf(arg1, sizeof arg1, "%d", p->msg.arg1);
+    else
+        snprintf(arg1, sizeof arg1, "0x%x", p->msg.arg1);
+
+    D("%s: %s: [%s] arg0=%s arg1=%s (len=%d) ",
+        name, func, cmd, arg0, arg1, len);
+    dump_hex(p->data, len);
+}
+#endif /* ADB_TRACE */
+
+static int
+read_packet(int  fd, const char* name, apacket** ppacket)
+{
+    char *p = (char*)ppacket;  /* really read a packet address */
+    int   r;
+    int   len = sizeof(*ppacket);
+    char  buff[8];
+    if (!name) {
+        snprintf(buff, sizeof buff, "fd=%d", fd);
+        name = buff;
+    }
+    while(len > 0) {
+        r = adb_read(fd, p, len);
+        if(r > 0) {
+            len -= r;
+            p   += r;
+        } else {
+            D("%s: read_packet (fd=%d), error ret=%d errno=%d: %s\n", name, fd, r, errno, strerror(errno));
+            if((r < 0) && (errno == EINTR)) continue;
+            return -1;
+        }
+    }
+
+#if ADB_TRACE
+    if (ADB_TRACING) {
+        dump_packet(name, "from remote", *ppacket);
+    }
+#endif
+    return 0;
+}
+
+static int
+write_packet(int  fd, const char* name, apacket** ppacket)
+{
+    char *p = (char*) ppacket;  /* we really write the packet address */
+    int r, len = sizeof(ppacket);
+    char buff[8];
+    if (!name) {
+        snprintf(buff, sizeof buff, "fd=%d", fd);
+        name = buff;
+    }
+
+#if ADB_TRACE
+    if (ADB_TRACING) {
+        dump_packet(name, "to remote", *ppacket);
+    }
+#endif
+    len = sizeof(ppacket);
+    while(len > 0) {
+        r = adb_write(fd, p, len);
+        if(r > 0) {
+            len -= r;
+            p += r;
+        } else {
+            D("%s: write_packet (fd=%d) error ret=%d errno=%d: %s\n", name, fd, r, errno, strerror(errno));
+            if((r < 0) && (errno == EINTR)) continue;
+            return -1;
+        }
+    }
+    return 0;
+}
+
+static void transport_socket_events(int fd, unsigned events, void *_t)
+{
+    atransport *t = _t;
+    D("transport_socket_events(fd=%d, events=%04x,...)\n", fd, events);
+    if(events & FDE_READ){
+        apacket *p = 0;
+        if(read_packet(fd, t->serial, &p)){
+            D("%s: failed to read packet from transport socket on fd %d\n", t->serial, fd);
+        } else {
+            handle_packet(p, (atransport *) _t);
+        }
+    }
+}
+
+void send_packet(apacket *p, atransport *t)
+{
+    unsigned char *x;
+    unsigned sum;
+    unsigned count;
+
+    p->msg.magic = p->msg.command ^ 0xffffffff;
+
+    count = p->msg.data_length;
+    x = (unsigned char *) p->data;
+    sum = 0;
+    while(count-- > 0){
+        sum += *x++;
+    }
+    p->msg.data_check = sum;
+
+    print_packet("send", p);
+
+    if (t == NULL) {
+        D("Transport is null \n");
+        // Zap errno because print_packet() and other stuff have errno effect.
+        errno = 0;
+        fatal_errno("Transport is null");
+    }
+
+    if(write_packet(t->transport_socket, t->serial, &p)){
+        fatal_errno("cannot enqueue packet on transport socket");
+    }
+}
+
+/* The transport is opened by transport_register_func before
+** the input and output threads are started.
+**
+** The output thread issues a SYNC(1, token) message to let
+** the input thread know to start things up.  In the event
+** of transport IO failure, the output thread will post a
+** SYNC(0,0) message to ensure shutdown.
+**
+** The transport will not actually be closed until both
+** threads exit, but the input thread will kick the transport
+** on its way out to disconnect the underlying device.
+*/
+
+static void *output_thread(void *_t)
+{
+    atransport *t = _t;
+    apacket *p;
+
+    D("%s: starting transport output thread on fd %d, SYNC online (%d)\n",
+       t->serial, t->fd, t->sync_token + 1);
+    p = get_apacket();
+    p->msg.command = A_SYNC;
+    p->msg.arg0 = 1;
+    p->msg.arg1 = ++(t->sync_token);
+    p->msg.magic = A_SYNC ^ 0xffffffff;
+    if(write_packet(t->fd, t->serial, &p)) {
+        put_apacket(p);
+        D("%s: failed to write SYNC packet\n", t->serial);
+        goto oops;
+    }
+
+    D("%s: data pump started\n", t->serial);
+    for(;;) {
+        p = get_apacket();
+
+        if(t->read_from_remote(p, t) == 0){
+            D("%s: received remote packet, sending to transport\n",
+              t->serial);
+            if(write_packet(t->fd, t->serial, &p)){
+                put_apacket(p);
+                D("%s: failed to write apacket to transport\n", t->serial);
+                goto oops;
+            }
+        } else {
+            D("%s: remote read failed for transport\n", t->serial);
+            put_apacket(p);
+            break;
+        }
+    }
+
+    D("%s: SYNC offline for transport\n", t->serial);
+    p = get_apacket();
+    p->msg.command = A_SYNC;
+    p->msg.arg0 = 0;
+    p->msg.arg1 = 0;
+    p->msg.magic = A_SYNC ^ 0xffffffff;
+    if(write_packet(t->fd, t->serial, &p)) {
+        put_apacket(p);
+        D("%s: failed to write SYNC apacket to transport", t->serial);
+    }
+
+oops:
+    D("%s: transport output thread is exiting\n", t->serial);
+    kick_transport(t);
+    transport_unref(t);
+    return 0;
+}
+
+static void *input_thread(void *_t)
+{
+    atransport *t = _t;
+    apacket *p;
+    int active = 0;
+
+    D("%s: starting transport input thread, reading from fd %d\n",
+       t->serial, t->fd);
+
+    for(;;){
+        if(read_packet(t->fd, t->serial, &p)) {
+            D("%s: failed to read apacket from transport on fd %d\n",
+               t->serial, t->fd );
+            break;
+        }
+        if(p->msg.command == A_SYNC){
+            if(p->msg.arg0 == 0) {
+                D("%s: transport SYNC offline\n", t->serial);
+                put_apacket(p);
+                break;
+            } else {
+                if(p->msg.arg1 == t->sync_token) {
+                    D("%s: transport SYNC online\n", t->serial);
+                    active = 1;
+                } else {
+                    D("%s: transport ignoring SYNC %d != %d\n",
+                      t->serial, p->msg.arg1, t->sync_token);
+                }
+            }
+        } else {
+            if(active) {
+                D("%s: transport got packet, sending to remote\n", t->serial);
+                t->write_to_remote(p, t);
+            } else {
+                D("%s: transport ignoring packet while offline\n", t->serial);
+            }
+        }
+
+        put_apacket(p);
+    }
+
+    // this is necessary to avoid a race condition that occured when a transport closes
+    // while a client socket is still active.
+    close_all_sockets(t);
+
+    D("%s: transport input thread is exiting, fd %d\n", t->serial, t->fd);
+    kick_transport(t);
+    transport_unref(t);
+    return 0;
+}
+
+
+static int transport_registration_send = -1;
+static int transport_registration_recv = -1;
+static fdevent transport_registration_fde;
+
+
+#if ADB_HOST
+static int list_transports_msg(char*  buffer, size_t  bufferlen)
+{
+    char  head[5];
+    int   len;
+
+    len = list_transports(buffer+4, bufferlen-4, 0);
+    snprintf(head, sizeof(head), "%04x", len);
+    memcpy(buffer, head, 4);
+    len += 4;
+    return len;
+}
+
+/* this adds support required by the 'track-devices' service.
+ * this is used to send the content of "list_transport" to any
+ * number of client connections that want it through a single
+ * live TCP connection
+ */
+typedef struct device_tracker  device_tracker;
+struct device_tracker {
+    asocket          socket;
+    int              update_needed;
+    device_tracker*  next;
+};
+
+/* linked list of all device trackers */
+static device_tracker*   device_tracker_list;
+
+static void
+device_tracker_remove( device_tracker*  tracker )
+{
+    device_tracker**  pnode = &device_tracker_list;
+    device_tracker*   node  = *pnode;
+
+    adb_mutex_lock( &transport_lock );
+    while (node) {
+        if (node == tracker) {
+            *pnode = node->next;
+            break;
+        }
+        pnode = &node->next;
+        node  = *pnode;
+    }
+    adb_mutex_unlock( &transport_lock );
+}
+
+static void
+device_tracker_close( asocket*  socket )
+{
+    device_tracker*  tracker = (device_tracker*) socket;
+    asocket*         peer    = socket->peer;
+
+    D( "device tracker %p removed\n", tracker);
+    if (peer) {
+        peer->peer = NULL;
+        peer->close(peer);
+    }
+    device_tracker_remove(tracker);
+    free(tracker);
+}
+
+static int
+device_tracker_enqueue( asocket*  socket, apacket*  p )
+{
+    /* you can't read from a device tracker, close immediately */
+    put_apacket(p);
+    device_tracker_close(socket);
+    return -1;
+}
+
+static int
+device_tracker_send( device_tracker*  tracker,
+                     const char*      buffer,
+                     int              len )
+{
+    apacket*  p = get_apacket();
+    asocket*  peer = tracker->socket.peer;
+
+    memcpy(p->data, buffer, len);
+    p->len = len;
+    return peer->enqueue( peer, p );
+}
+
+
+static void
+device_tracker_ready( asocket*  socket )
+{
+    device_tracker*  tracker = (device_tracker*) socket;
+
+    /* we want to send the device list when the tracker connects
+    * for the first time, even if no update occured */
+    if (tracker->update_needed > 0) {
+        char  buffer[1024];
+        int   len;
+
+        tracker->update_needed = 0;
+
+        len = list_transports_msg(buffer, sizeof(buffer));
+        device_tracker_send(tracker, buffer, len);
+    }
+}
+
+
+asocket*
+create_device_tracker(void)
+{
+    device_tracker*  tracker = calloc(1,sizeof(*tracker));
+
+    if(tracker == 0) fatal("cannot allocate device tracker");
+
+    D( "device tracker %p created\n", tracker);
+
+    tracker->socket.enqueue = device_tracker_enqueue;
+    tracker->socket.ready   = device_tracker_ready;
+    tracker->socket.close   = device_tracker_close;
+    tracker->update_needed  = 1;
+
+    tracker->next       = device_tracker_list;
+    device_tracker_list = tracker;
+
+    return &tracker->socket;
+}
+
+
+/* call this function each time the transport list has changed */
+void  update_transports(void)
+{
+    char             buffer[1024];
+    int              len;
+    device_tracker*  tracker;
+
+    len = list_transports_msg(buffer, sizeof(buffer));
+
+    tracker = device_tracker_list;
+    while (tracker != NULL) {
+        device_tracker*  next = tracker->next;
+        /* note: this may destroy the tracker if the connection is closed */
+        device_tracker_send(tracker, buffer, len);
+        tracker = next;
+    }
+}
+#else
+void  update_transports(void)
+{
+    // nothing to do on the device side
+}
+#endif // ADB_HOST
+
+typedef struct tmsg tmsg;
+struct tmsg
+{
+    atransport *transport;
+    int         action;
+};
+
+static int
+transport_read_action(int  fd, struct tmsg*  m)
+{
+    char *p   = (char*)m;
+    int   len = sizeof(*m);
+    int   r;
+
+    while(len > 0) {
+        r = adb_read(fd, p, len);
+        if(r > 0) {
+            len -= r;
+            p   += r;
+        } else {
+            if((r < 0) && (errno == EINTR)) continue;
+            D("transport_read_action: on fd %d, error %d: %s\n",
+              fd, errno, strerror(errno));
+            return -1;
+        }
+    }
+    return 0;
+}
+
+static int
+transport_write_action(int  fd, struct tmsg*  m)
+{
+    char *p   = (char*)m;
+    int   len = sizeof(*m);
+    int   r;
+
+    while(len > 0) {
+        r = adb_write(fd, p, len);
+        if(r > 0) {
+            len -= r;
+            p   += r;
+        } else {
+            if((r < 0) && (errno == EINTR)) continue;
+            D("transport_write_action: on fd %d, error %d: %s\n",
+              fd, errno, strerror(errno));
+            return -1;
+        }
+    }
+    return 0;
+}
+
+static void transport_registration_func(int _fd, unsigned ev, void *data)
+{
+    tmsg m;
+    adb_thread_t output_thread_ptr;
+    adb_thread_t input_thread_ptr;
+    int s[2];
+    atransport *t;
+
+    if(!(ev & FDE_READ)) {
+        return;
+    }
+
+    if(transport_read_action(_fd, &m)) {
+        fatal_errno("cannot read transport registration socket");
+    }
+
+    t = m.transport;
+
+    if(m.action == 0){
+        D("transport: %s removing and free'ing %d\n", t->serial, t->transport_socket);
+
+            /* IMPORTANT: the remove closes one half of the
+            ** socket pair.  The close closes the other half.
+            */
+        fdevent_remove(&(t->transport_fde));
+        adb_close(t->fd);
+
+        adb_mutex_lock(&transport_lock);
+        t->next->prev = t->prev;
+        t->prev->next = t->next;
+        adb_mutex_unlock(&transport_lock);
+
+        run_transport_disconnects(t);
+
+        if (t->product)
+            free(t->product);
+        if (t->serial)
+            free(t->serial);
+        if (t->model)
+            free(t->model);
+        if (t->device)
+            free(t->device);
+        if (t->devpath)
+            free(t->devpath);
+
+        memset(t,0xee,sizeof(atransport));
+        free(t);
+
+        update_transports();
+        return;
+    }
+
+    /* don't create transport threads for inaccessible devices */
+    if (t->connection_state != CS_NOPERM) {
+        /* initial references are the two threads */
+        t->ref_count = 2;
+
+        if(adb_socketpair(s)) {
+            fatal_errno("cannot open transport socketpair");
+        }
+
+        D("transport: %s (%d,%d) starting\n", t->serial, s[0], s[1]);
+
+        t->transport_socket = s[0];
+        t->fd = s[1];
+
+        fdevent_install(&(t->transport_fde),
+                        t->transport_socket,
+                        transport_socket_events,
+                        t);
+
+        fdevent_set(&(t->transport_fde), FDE_READ);
+
+        if(adb_thread_create(&input_thread_ptr, input_thread, t)){
+            fatal_errno("cannot create input thread");
+        }
+
+        if(adb_thread_create(&output_thread_ptr, output_thread, t)){
+            fatal_errno("cannot create output thread");
+        }
+    }
+
+    adb_mutex_lock(&transport_lock);
+    /* remove from pending list */
+    t->next->prev = t->prev;
+    t->prev->next = t->next;
+    /* put us on the master device list */
+    t->next = &transport_list;
+    t->prev = transport_list.prev;
+    t->next->prev = t;
+    t->prev->next = t;
+    adb_mutex_unlock(&transport_lock);
+
+    t->disconnects.next = t->disconnects.prev = &t->disconnects;
+
+    update_transports();
+}
+
+void init_transport_registration(void)
+{
+    int s[2];
+
+    if(adb_socketpair(s)){
+        fatal_errno("cannot open transport registration socketpair");
+    }
+
+    transport_registration_send = s[0];
+    transport_registration_recv = s[1];
+
+    fdevent_install(&transport_registration_fde,
+                    transport_registration_recv,
+                    transport_registration_func,
+                    0);
+
+    fdevent_set(&transport_registration_fde, FDE_READ);
+}
+
+/* the fdevent select pump is single threaded */
+static void register_transport(atransport *transport)
+{
+    tmsg m;
+    m.transport = transport;
+    m.action = 1;
+    D("transport: %s registered\n", transport->serial);
+    if(transport_write_action(transport_registration_send, &m)) {
+        fatal_errno("cannot write transport registration socket\n");
+    }
+}
+
+static void remove_transport(atransport *transport)
+{
+    tmsg m;
+    m.transport = transport;
+    m.action = 0;
+    D("transport: %s removed\n", transport->serial);
+    if(transport_write_action(transport_registration_send, &m)) {
+        fatal_errno("cannot write transport registration socket\n");
+    }
+}
+
+
+static void transport_unref_locked(atransport *t)
+{
+    t->ref_count--;
+    if (t->ref_count == 0) {
+        D("transport: %s unref (kicking and closing)\n", t->serial);
+        if (!t->kicked) {
+            t->kicked = 1;
+            t->kick(t);
+        }
+        t->close(t);
+        remove_transport(t);
+    } else {
+        D("transport: %s unref (count=%d)\n", t->serial, t->ref_count);
+    }
+}
+
+static void transport_unref(atransport *t)
+{
+    if (t) {
+        adb_mutex_lock(&transport_lock);
+        transport_unref_locked(t);
+        adb_mutex_unlock(&transport_lock);
+    }
+}
+
+void add_transport_disconnect(atransport*  t, adisconnect*  dis)
+{
+    adb_mutex_lock(&transport_lock);
+    dis->next       = &t->disconnects;
+    dis->prev       = dis->next->prev;
+    dis->prev->next = dis;
+    dis->next->prev = dis;
+    adb_mutex_unlock(&transport_lock);
+}
+
+void remove_transport_disconnect(atransport*  t, adisconnect*  dis)
+{
+    dis->prev->next = dis->next;
+    dis->next->prev = dis->prev;
+    dis->next = dis->prev = dis;
+}
+
+static int qual_char_is_invalid(char ch)
+{
+    if ('A' <= ch && ch <= 'Z')
+        return 0;
+    if ('a' <= ch && ch <= 'z')
+        return 0;
+    if ('0' <= ch && ch <= '9')
+        return 0;
+    return 1;
+}
+
+static int qual_match(const char *to_test,
+                      const char *prefix, const char *qual, int sanitize_qual)
+{
+    if (!to_test || !*to_test)
+        /* Return true if both the qual and to_test are null strings. */
+        return !qual || !*qual;
+
+    if (!qual)
+        return 0;
+
+    if (prefix) {
+        while (*prefix) {
+            if (*prefix++ != *to_test++)
+                return 0;
+        }
+    }
+
+    while (*qual) {
+        char ch = *qual++;
+        if (sanitize_qual && qual_char_is_invalid(ch))
+            ch = '_';
+        if (ch != *to_test++)
+            return 0;
+    }
+
+    /* Everything matched so far.  Return true if *to_test is a NUL. */
+    return !*to_test;
+}
+
+atransport *acquire_one_transport(int state, transport_type ttype, const char* serial, char** error_out)
+{
+    atransport *t;
+    atransport *result = NULL;
+    int ambiguous = 0;
+
+retry:
+    if (error_out)
+        *error_out = "device not found";
+
+    adb_mutex_lock(&transport_lock);
+    for (t = transport_list.next; t != &transport_list; t = t->next) {
+        if (t->connection_state == CS_NOPERM) {
+        if (error_out)
+        {
+            *error_out = "insufficient permissions for device";
+        }
+            continue;
+        }
+
+        /* check for matching serial number */
+        if (serial) {
+            if ((t->serial && !strcmp(serial, t->serial)) ||
+                (t->devpath && !strcmp(serial, t->devpath)) ||
+                qual_match(serial, "product:", t->product, 0) ||
+                qual_match(serial, "model:", t->model, 1) ||
+                qual_match(serial, "device:", t->device, 0)) {
+                if (result) {
+                    if (error_out)
+                        *error_out = "more than one device";
+                    ambiguous = 1;
+                    result = NULL;
+                    break;
+                }
+                result = t;
+            }
+        } else {
+            if (ttype == kTransportUsb && t->type == kTransportUsb) {
+                if (result) {
+                    if (error_out)
+                        *error_out = "more than one device";
+                    ambiguous = 1;
+                    result = NULL;
+                    break;
+                }
+                result = t;
+            } else if (ttype == kTransportLocal && t->type == kTransportLocal) {
+                if (result) {
+                    if (error_out)
+                        *error_out = "more than one emulator";
+                    ambiguous = 1;
+                    result = NULL;
+                    break;
+                }
+                result = t;
+            } else if (ttype == kTransportAny) {
+                if (result) {
+                    if (error_out)
+                        *error_out = "more than one device and emulator";
+                    ambiguous = 1;
+                    result = NULL;
+                    break;
+                }
+                result = t;
+            }
+        }
+    }
+    adb_mutex_unlock(&transport_lock);
+
+    if (result) {
+        if (result->connection_state == CS_UNAUTHORIZED) {
+            if (error_out)
+                *error_out = "device unauthorized. Please check the confirmation dialog on your device.";
+            result = NULL;
+        }
+
+         /* offline devices are ignored -- they are either being born or dying */
+        if (result && result->connection_state == CS_OFFLINE) {
+            if (error_out)
+                *error_out = "device offline";
+            result = NULL;
+        }
+         /* check for required connection state */
+        if (result && state != CS_ANY && result->connection_state != state) {
+            if (error_out)
+                *error_out = "invalid device state";
+            result = NULL;
+        }
+    }
+
+    if (result) {
+        /* found one that we can take */
+        if (error_out)
+            *error_out = NULL;
+    } else if (state != CS_ANY && (serial || !ambiguous)) {
+        adb_sleep_ms(1000);
+        goto retry;
+    }
+
+    return result;
+}
+
+#if ADB_HOST
+static const char *statename(atransport *t)
+{
+    switch(t->connection_state){
+    case CS_OFFLINE: return "offline";
+    case CS_BOOTLOADER: return "bootloader";
+    case CS_DEVICE: return "device";
+    case CS_HOST: return "host";
+    case CS_RECOVERY: return "recovery";
+    case CS_SIDELOAD: return "sideload";
+    case CS_NOPERM: return "no permissions";
+    case CS_UNAUTHORIZED: return "unauthorized";
+    default: return "unknown";
+    }
+}
+
+static void add_qual(char **buf, size_t *buf_size,
+                     const char *prefix, const char *qual, int sanitize_qual)
+{
+    size_t len;
+    int prefix_len;
+
+    if (!buf || !*buf || !buf_size || !*buf_size || !qual || !*qual)
+        return;
+
+    len = snprintf(*buf, *buf_size, "%s%n%s", prefix, &prefix_len, qual);
+
+    if (sanitize_qual) {
+        char *cp;
+        for (cp = *buf + prefix_len; cp < *buf + len; cp++) {
+            if (qual_char_is_invalid(*cp))
+                *cp = '_';
+        }
+    }
+
+    *buf_size -= len;
+    *buf += len;
+}
+
+static size_t format_transport(atransport *t, char *buf, size_t bufsize,
+                               int long_listing)
+{
+    const char* serial = t->serial;
+    if (!serial || !serial[0])
+        serial = "????????????";
+
+    if (!long_listing) {
+        return snprintf(buf, bufsize, "%s\t%s\n", serial, statename(t));
+    } else {
+        size_t len, remaining = bufsize;
+
+        len = snprintf(buf, remaining, "%-22s %s", serial, statename(t));
+        remaining -= len;
+        buf += len;
+
+        add_qual(&buf, &remaining, " ", t->devpath, 0);
+        add_qual(&buf, &remaining, " product:", t->product, 0);
+        add_qual(&buf, &remaining, " model:", t->model, 1);
+        add_qual(&buf, &remaining, " device:", t->device, 0);
+
+        len = snprintf(buf, remaining, "\n");
+        remaining -= len;
+
+        return bufsize - remaining;
+    }
+}
+
+int list_transports(char *buf, size_t  bufsize, int long_listing)
+{
+    char*       p   = buf;
+    char*       end = buf + bufsize;
+    int         len;
+    atransport *t;
+
+        /* XXX OVERRUN PROBLEMS XXX */
+    adb_mutex_lock(&transport_lock);
+    for(t = transport_list.next; t != &transport_list; t = t->next) {
+        len = format_transport(t, p, end - p, long_listing);
+        if (p + len >= end) {
+            /* discard last line if buffer is too short */
+            break;
+        }
+        p += len;
+    }
+    p[0] = 0;
+    adb_mutex_unlock(&transport_lock);
+    return p - buf;
+}
+
+
+/* hack for osx */
+void close_usb_devices()
+{
+    atransport *t;
+
+    adb_mutex_lock(&transport_lock);
+    for(t = transport_list.next; t != &transport_list; t = t->next) {
+        if ( !t->kicked ) {
+            t->kicked = 1;
+            t->kick(t);
+        }
+    }
+    adb_mutex_unlock(&transport_lock);
+}
+#endif // ADB_HOST
+
+int register_socket_transport(int s, const char *serial, int port, int local)
+{
+    atransport *t = calloc(1, sizeof(atransport));
+    atransport *n;
+    char buff[32];
+
+    if (!serial) {
+        snprintf(buff, sizeof buff, "T-%p", t);
+        serial = buff;
+    }
+    D("transport: %s init'ing for socket %d, on port %d\n", serial, s, port);
+    if (init_socket_transport(t, s, port, local) < 0) {
+        free(t);
+        return -1;
+    }
+
+    adb_mutex_lock(&transport_lock);
+    for (n = pending_list.next; n != &pending_list; n = n->next) {
+        if (n->serial && !strcmp(serial, n->serial)) {
+            adb_mutex_unlock(&transport_lock);
+            free(t);
+            return -1;
+        }
+    }
+
+    for (n = transport_list.next; n != &transport_list; n = n->next) {
+        if (n->serial && !strcmp(serial, n->serial)) {
+            adb_mutex_unlock(&transport_lock);
+            free(t);
+            return -1;
+        }
+    }
+
+    t->next = &pending_list;
+    t->prev = pending_list.prev;
+    t->next->prev = t;
+    t->prev->next = t;
+    t->serial = strdup(serial);
+    adb_mutex_unlock(&transport_lock);
+
+    register_transport(t);
+    return 0;
+}
+
+#if ADB_HOST
+atransport *find_transport(const char *serial)
+{
+    atransport *t;
+
+    adb_mutex_lock(&transport_lock);
+    for(t = transport_list.next; t != &transport_list; t = t->next) {
+        if (t->serial && !strcmp(serial, t->serial)) {
+            break;
+        }
+     }
+    adb_mutex_unlock(&transport_lock);
+
+    if (t != &transport_list)
+        return t;
+    else
+        return 0;
+}
+
+void unregister_transport(atransport *t)
+{
+    adb_mutex_lock(&transport_lock);
+    t->next->prev = t->prev;
+    t->prev->next = t->next;
+    adb_mutex_unlock(&transport_lock);
+
+    kick_transport(t);
+    transport_unref(t);
+}
+
+// unregisters all non-emulator TCP transports
+void unregister_all_tcp_transports()
+{
+    atransport *t, *next;
+    adb_mutex_lock(&transport_lock);
+    for (t = transport_list.next; t != &transport_list; t = next) {
+        next = t->next;
+        if (t->type == kTransportLocal && t->adb_port == 0) {
+            t->next->prev = t->prev;
+            t->prev->next = next;
+            // we cannot call kick_transport when holding transport_lock
+            if (!t->kicked)
+            {
+                t->kicked = 1;
+                t->kick(t);
+            }
+            transport_unref_locked(t);
+        }
+     }
+
+    adb_mutex_unlock(&transport_lock);
+}
+
+#endif
+
+void register_usb_transport(usb_handle *usb, const char *serial, const char *devpath, unsigned writeable)
+{
+    atransport *t = calloc(1, sizeof(atransport));
+    D("transport: %p init'ing for usb_handle %p (sn='%s')\n", t, usb,
+      serial ? serial : "");
+    init_usb_transport(t, usb, (writeable ? CS_OFFLINE : CS_NOPERM));
+    if(serial) {
+        t->serial = strdup(serial);
+    }
+    if(devpath) {
+        t->devpath = strdup(devpath);
+    }
+
+    adb_mutex_lock(&transport_lock);
+    t->next = &pending_list;
+    t->prev = pending_list.prev;
+    t->next->prev = t;
+    t->prev->next = t;
+    adb_mutex_unlock(&transport_lock);
+
+    register_transport(t);
+}
+
+/* this should only be used for transports with connection_state == CS_NOPERM */
+void unregister_usb_transport(usb_handle *usb)
+{
+    atransport *t;
+    adb_mutex_lock(&transport_lock);
+    for(t = transport_list.next; t != &transport_list; t = t->next) {
+        if (t->usb == usb && t->connection_state == CS_NOPERM) {
+            t->next->prev = t->prev;
+            t->prev->next = t->next;
+            break;
+        }
+     }
+    adb_mutex_unlock(&transport_lock);
+}
+
+#undef TRACE_TAG
+#define TRACE_TAG  TRACE_RWX
+
+int readx(int fd, void *ptr, size_t len)
+{
+    char *p = ptr;
+    int r;
+#if ADB_TRACE
+    size_t len0 = len;
+#endif
+    D("readx: fd=%d wanted=%zu\n", fd, len);
+    while(len > 0) {
+        r = adb_read(fd, p, len);
+        if(r > 0) {
+            len -= r;
+            p += r;
+        } else {
+            if (r < 0) {
+                D("readx: fd=%d error %d: %s\n", fd, errno, strerror(errno));
+                if (errno == EINTR)
+                    continue;
+            } else {
+                D("readx: fd=%d disconnected\n", fd);
+            }
+            return -1;
+        }
+    }
+
+#if ADB_TRACE
+    D("readx: fd=%d wanted=%zu got=%zu\n", fd, len0, len0 - len);
+    dump_hex( ptr, len0 );
+#endif
+    return 0;
+}
+
+int writex(int fd, const void *ptr, size_t len)
+{
+    char *p = (char*) ptr;
+    int r;
+
+#if ADB_TRACE
+    D("writex: fd=%d len=%d: ", fd, (int)len);
+    dump_hex( ptr, len );
+#endif
+    while(len > 0) {
+        r = adb_write(fd, p, len);
+        if(r > 0) {
+            len -= r;
+            p += r;
+        } else {
+            if (r < 0) {
+                D("writex: fd=%d error %d: %s\n", fd, errno, strerror(errno));
+                if (errno == EINTR)
+                    continue;
+                if (errno == EAGAIN) {
+                    adb_sleep_ms(1); // just yield some cpu time
+                    continue;
+                }
+            } else {
+                D("writex: fd=%d disconnected\n", fd);
+            }
+            return -1;
+        }
+    }
+    return 0;
+}
+
+int check_header(apacket *p)
+{
+    if(p->msg.magic != (p->msg.command ^ 0xffffffff)) {
+        D("check_header(): invalid magic\n");
+        return -1;
+    }
+
+    if(p->msg.data_length > MAX_PAYLOAD) {
+        D("check_header(): %d > MAX_PAYLOAD\n", p->msg.data_length);
+        return -1;
+    }
+
+    return 0;
+}
+
+int check_data(apacket *p)
+{
+    unsigned count, sum;
+    unsigned char *x;
+
+    count = p->msg.data_length;
+    x = p->data;
+    sum = 0;
+    while(count-- > 0) {
+        sum += *x++;
+    }
+
+    if(sum != p->msg.data_check) {
+        return -1;
+    } else {
+        return 0;
+    }
+}
diff --git a/package/utils/adbd/src/adb/transport.h b/package/utils/adbd/src/adb/transport.h
new file mode 100644
index 0000000..992e052
--- /dev/null
+++ b/package/utils/adbd/src/adb/transport.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2011 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 __TRANSPORT_H
+#define __TRANSPORT_H
+
+/* convenience wrappers around read/write that will retry on
+** EINTR and/or short read/write.  Returns 0 on success, -1
+** on error or EOF.
+*/
+int readx(int fd, void *ptr, size_t len);
+int writex(int fd, const void *ptr, size_t len);
+#endif   /* __TRANSPORT_H */
diff --git a/package/utils/adbd/src/adb/transport_local.c b/package/utils/adbd/src/adb/transport_local.c
new file mode 100644
index 0000000..948cc15
--- /dev/null
+++ b/package/utils/adbd/src/adb/transport_local.c
@@ -0,0 +1,444 @@
+/*
+ * 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 <errno.h>
+
+#include "sysdeps.h"
+#include <sys/types.h>
+#if !ADB_HOST
+#include <cutils/properties.h>
+#endif
+
+#define  TRACE_TAG  TRACE_TRANSPORT
+#include "adb.h"
+
+#ifdef HAVE_BIG_ENDIAN
+#define H4(x)	(((x) & 0xFF000000) >> 24) | (((x) & 0x00FF0000) >> 8) | (((x) & 0x0000FF00) << 8) | (((x) & 0x000000FF) << 24)
+static inline void fix_endians(apacket *p)
+{
+    p->msg.command     = H4(p->msg.command);
+    p->msg.arg0        = H4(p->msg.arg0);
+    p->msg.arg1        = H4(p->msg.arg1);
+    p->msg.data_length = H4(p->msg.data_length);
+    p->msg.data_check  = H4(p->msg.data_check);
+    p->msg.magic       = H4(p->msg.magic);
+}
+#else
+#define fix_endians(p) do {} while (0)
+#endif
+
+#if ADB_HOST
+/* we keep a list of opened transports. The atransport struct knows to which
+ * local transport it is connected. The list is used to detect when we're
+ * trying to connect twice to a given local transport.
+ */
+#define  ADB_LOCAL_TRANSPORT_MAX  64
+
+ADB_MUTEX_DEFINE( local_transports_lock );
+
+static atransport*  local_transports[ ADB_LOCAL_TRANSPORT_MAX ];
+#endif /* ADB_HOST */
+
+static int remote_read(apacket *p, atransport *t)
+{
+    if(readx(t->sfd, &p->msg, sizeof(amessage))){
+        D("remote local: read terminated (message)\n");
+        return -1;
+    }
+
+    fix_endians(p);
+
+#if 0 && defined HAVE_BIG_ENDIAN
+    D("read remote packet: %04x arg0=%0x arg1=%0x data_length=%0x data_check=%0x magic=%0x\n",
+      p->msg.command, p->msg.arg0, p->msg.arg1, p->msg.data_length, p->msg.data_check, p->msg.magic);
+#endif
+    if(check_header(p)) {
+        D("bad header: terminated (data)\n");
+        return -1;
+    }
+
+    if(readx(t->sfd, p->data, p->msg.data_length)){
+        D("remote local: terminated (data)\n");
+        return -1;
+    }
+
+    if(check_data(p)) {
+        D("bad data: terminated (data)\n");
+        return -1;
+    }
+
+    return 0;
+}
+
+static int remote_write(apacket *p, atransport *t)
+{
+    int   length = p->msg.data_length;
+
+    fix_endians(p);
+
+#if 0 && defined HAVE_BIG_ENDIAN
+    D("write remote packet: %04x arg0=%0x arg1=%0x data_length=%0x data_check=%0x magic=%0x\n",
+      p->msg.command, p->msg.arg0, p->msg.arg1, p->msg.data_length, p->msg.data_check, p->msg.magic);
+#endif
+    if(writex(t->sfd, &p->msg, sizeof(amessage) + length)) {
+        D("remote local: write terminated\n");
+        return -1;
+    }
+
+    return 0;
+}
+
+
+int local_connect(int port) {
+    return local_connect_arbitrary_ports(port-1, port);
+}
+
+int local_connect_arbitrary_ports(int console_port, int adb_port)
+{
+    char buf[64];
+    int  fd = -1;
+
+#if ADB_HOST
+    const char *host = getenv("ADBHOST");
+    if (host) {
+        fd = socket_network_client(host, adb_port, SOCK_STREAM);
+    }
+#endif
+    if (fd < 0) {
+        fd = socket_loopback_client(adb_port, SOCK_STREAM);
+    }
+
+    if (fd >= 0) {
+        D("client: connected on remote on fd %d\n", fd);
+        close_on_exec(fd);
+        disable_tcp_nagle(fd);
+        snprintf(buf, sizeof buf, "%s%d", LOCAL_CLIENT_PREFIX, console_port);
+        register_socket_transport(fd, buf, adb_port, 1);
+        return 0;
+    }
+    return -1;
+}
+
+
+static void *client_socket_thread(void *x)
+{
+#if ADB_HOST
+    int  port  = DEFAULT_ADB_LOCAL_TRANSPORT_PORT;
+    int  count = ADB_LOCAL_TRANSPORT_MAX;
+
+    D("transport: client_socket_thread() starting\n");
+
+    /* try to connect to any number of running emulator instances     */
+    /* this is only done when ADB starts up. later, each new emulator */
+    /* will send a message to ADB to indicate that is is starting up  */
+    for ( ; count > 0; count--, port += 2 ) {
+        (void) local_connect(port);
+    }
+#endif
+    return 0;
+}
+
+static void *server_socket_thread(void * arg)
+{
+    int serverfd, fd;
+    struct sockaddr addr;
+    socklen_t alen;
+    int port = (int) (uintptr_t) arg;
+
+    D("transport: server_socket_thread() starting\n");
+    serverfd = -1;
+    for(;;) {
+        if(serverfd == -1) {
+            serverfd = socket_inaddr_any_server(port, SOCK_STREAM);
+            if(serverfd < 0) {
+                D("server: cannot bind socket yet\n");
+                adb_sleep_ms(1000);
+                continue;
+            }
+            close_on_exec(serverfd);
+        }
+
+        alen = sizeof(addr);
+        D("server: trying to get new connection from %d\n", port);
+        fd = adb_socket_accept(serverfd, &addr, &alen);
+        if(fd >= 0) {
+            D("server: new connection on fd %d\n", fd);
+            close_on_exec(fd);
+            disable_tcp_nagle(fd);
+            register_socket_transport(fd, "host", port, 1);
+        }
+    }
+    D("transport: server_socket_thread() exiting\n");
+    return 0;
+}
+
+/* This is relevant only for ADB daemon running inside the emulator. */
+#if !ADB_HOST
+/*
+ * Redefine open and write for qemu_pipe.h that contains inlined references
+ * to those routines. We will redifine them back after qemu_pipe.h inclusion.
+ */
+#undef open
+#undef write
+#define open    adb_open
+#define write   adb_write
+#include <hardware/qemu_pipe.h>
+#undef open
+#undef write
+#define open    ___xxx_open
+#define write   ___xxx_write
+
+/* A worker thread that monitors host connections, and registers a transport for
+ * every new host connection. This thread replaces server_socket_thread on
+ * condition that adbd daemon runs inside the emulator, and emulator uses QEMUD
+ * pipe to communicate with adbd daemon inside the guest. This is done in order
+ * to provide more robust communication channel between ADB host and guest. The
+ * main issue with server_socket_thread approach is that it runs on top of TCP,
+ * and thus is sensitive to network disruptions. For instance, the
+ * ConnectionManager may decide to reset all network connections, in which case
+ * the connection between ADB host and guest will be lost. To make ADB traffic
+ * independent from the network, we use here 'adb' QEMUD service to transfer data
+ * between the host, and the guest. See external/qemu/android/adb-*.* that
+ * implements the emulator's side of the protocol. Another advantage of using
+ * QEMUD approach is that ADB will be up much sooner, since it doesn't depend
+ * anymore on network being set up.
+ * The guest side of the protocol contains the following phases:
+ * - Connect with adb QEMUD service. In this phase a handle to 'adb' QEMUD service
+ *   is opened, and it becomes clear whether or not emulator supports that
+ *   protocol.
+ * - Wait for the ADB host to create connection with the guest. This is done by
+ *   sending an 'accept' request to the adb QEMUD service, and waiting on
+ *   response.
+ * - When new ADB host connection is accepted, the connection with adb QEMUD
+ *   service is registered as the transport, and a 'start' request is sent to the
+ *   adb QEMUD service, indicating that the guest is ready to receive messages.
+ *   Note that the guest will ignore messages sent down from the emulator before
+ *   the transport registration is completed. That's why we need to send the
+ *   'start' request after the transport is registered.
+ */
+static void *qemu_socket_thread(void * arg)
+{
+/* 'accept' request to the adb QEMUD service. */
+static const char _accept_req[] = "accept";
+/* 'start' request to the adb QEMUD service. */
+static const char _start_req[]  = "start";
+/* 'ok' reply from the adb QEMUD service. */
+static const char _ok_resp[]    = "ok";
+
+    const int port = (int) (uintptr_t) arg;
+    int res, fd;
+    char tmp[256];
+    char con_name[32];
+
+    D("transport: qemu_socket_thread() starting\n");
+
+    /* adb QEMUD service connection request. */
+    snprintf(con_name, sizeof(con_name), "qemud:adb:%d", port);
+
+    /* Connect to the adb QEMUD service. */
+    fd = qemu_pipe_open(con_name);
+    if (fd < 0) {
+        /* This could be an older version of the emulator, that doesn't
+         * implement adb QEMUD service. Fall back to the old TCP way. */
+        adb_thread_t thr;
+        D("adb service is not available. Falling back to TCP socket.\n");
+        adb_thread_create(&thr, server_socket_thread, arg);
+        return 0;
+    }
+
+    for(;;) {
+        /*
+         * Wait till the host creates a new connection.
+         */
+
+        /* Send the 'accept' request. */
+        res = adb_write(fd, _accept_req, strlen(_accept_req));
+        if ((size_t)res == strlen(_accept_req)) {
+            /* Wait for the response. In the response we expect 'ok' on success,
+             * or 'ko' on failure. */
+            res = adb_read(fd, tmp, sizeof(tmp));
+            if (res != 2 || memcmp(tmp, _ok_resp, 2)) {
+                D("Accepting ADB host connection has failed.\n");
+                adb_close(fd);
+            } else {
+                /* Host is connected. Register the transport, and start the
+                 * exchange. */
+                register_socket_transport(fd, "host", port, 1);
+                adb_write(fd, _start_req, strlen(_start_req));
+            }
+
+            /* Prepare for accepting of the next ADB host connection. */
+            fd = qemu_pipe_open(con_name);
+            if (fd < 0) {
+                D("adb service become unavailable.\n");
+                return 0;
+            }
+        } else {
+            D("Unable to send the '%s' request to ADB service.\n", _accept_req);
+            return 0;
+        }
+    }
+    D("transport: qemu_socket_thread() exiting\n");
+    return 0;
+}
+#endif  // !ADB_HOST
+
+void local_init(int port)
+{
+    adb_thread_t thr;
+    void* (*func)(void *);
+
+    if(HOST) {
+        func = client_socket_thread;
+    } else {
+#if ADB_HOST
+        func = server_socket_thread;
+#else
+        /* For the adbd daemon in the system image we need to distinguish
+         * between the device, and the emulator. */
+        char is_qemu[PROPERTY_VALUE_MAX];
+        property_get("ro.kernel.qemu", is_qemu, "");
+        if (!strcmp(is_qemu, "1")) {
+            /* Running inside the emulator: use QEMUD pipe as the transport. */
+            func = qemu_socket_thread;
+        } else {
+            /* Running inside the device: use TCP socket as the transport. */
+            func = server_socket_thread;
+        }
+#endif // !ADB_HOST
+    }
+
+    D("transport: local %s init\n", HOST ? "client" : "server");
+
+    if(adb_thread_create(&thr, func, (void *) (uintptr_t) port)) {
+        fatal_errno("cannot create local socket %s thread",
+                    HOST ? "client" : "server");
+    }
+}
+
+static void remote_kick(atransport *t)
+{
+    int fd = t->sfd;
+    t->sfd = -1;
+    adb_shutdown(fd);
+    adb_close(fd);
+
+#if ADB_HOST
+    if(HOST) {
+        int  nn;
+        adb_mutex_lock( &local_transports_lock );
+        for (nn = 0; nn < ADB_LOCAL_TRANSPORT_MAX; nn++) {
+            if (local_transports[nn] == t) {
+                local_transports[nn] = NULL;
+                break;
+            }
+        }
+        adb_mutex_unlock( &local_transports_lock );
+    }
+#endif
+}
+
+static void remote_close(atransport *t)
+{
+    adb_close(t->fd);
+}
+
+
+#if ADB_HOST
+/* Only call this function if you already hold local_transports_lock. */
+atransport* find_emulator_transport_by_adb_port_locked(int adb_port)
+{
+    int i;
+    for (i = 0; i < ADB_LOCAL_TRANSPORT_MAX; i++) {
+        if (local_transports[i] && local_transports[i]->adb_port == adb_port) {
+            return local_transports[i];
+        }
+    }
+    return NULL;
+}
+
+atransport* find_emulator_transport_by_adb_port(int adb_port)
+{
+    adb_mutex_lock( &local_transports_lock );
+    atransport* result = find_emulator_transport_by_adb_port_locked(adb_port);
+    adb_mutex_unlock( &local_transports_lock );
+    return result;
+}
+
+/* Only call this function if you already hold local_transports_lock. */
+int get_available_local_transport_index_locked()
+{
+    int i;
+    for (i = 0; i < ADB_LOCAL_TRANSPORT_MAX; i++) {
+        if (local_transports[i] == NULL) {
+            return i;
+        }
+    }
+    return -1;
+}
+
+int get_available_local_transport_index()
+{
+    adb_mutex_lock( &local_transports_lock );
+    int result = get_available_local_transport_index_locked();
+    adb_mutex_unlock( &local_transports_lock );
+    return result;
+}
+#endif
+
+int init_socket_transport(atransport *t, int s, int adb_port, int local)
+{
+    int  fail = 0;
+
+    t->kick = remote_kick;
+    t->close = remote_close;
+    t->read_from_remote = remote_read;
+    t->write_to_remote = remote_write;
+    t->sfd = s;
+    t->sync_token = 1;
+    t->connection_state = CS_OFFLINE;
+    t->type = kTransportLocal;
+    t->adb_port = 0;
+
+#if ADB_HOST
+    if (HOST && local) {
+        adb_mutex_lock( &local_transports_lock );
+        {
+            t->adb_port = adb_port;
+            atransport* existing_transport =
+                    find_emulator_transport_by_adb_port_locked(adb_port);
+            int index = get_available_local_transport_index_locked();
+            if (existing_transport != NULL) {
+                D("local transport for port %d already registered (%p)?\n",
+                adb_port, existing_transport);
+                fail = -1;
+            } else if (index < 0) {
+                // Too many emulators.
+                D("cannot register more emulators. Maximum is %d\n",
+                        ADB_LOCAL_TRANSPORT_MAX);
+                fail = -1;
+            } else {
+                local_transports[index] = t;
+            }
+       }
+       adb_mutex_unlock( &local_transports_lock );
+    }
+#endif
+    return fail;
+}
diff --git a/package/utils/adbd/src/adb/transport_usb.c b/package/utils/adbd/src/adb/transport_usb.c
new file mode 100644
index 0000000..ee6b637
--- /dev/null
+++ b/package/utils/adbd/src/adb/transport_usb.c
@@ -0,0 +1,148 @@
+/*
+ * 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 <sysdeps.h>
+
+#define  TRACE_TAG  TRACE_TRANSPORT
+#include "adb.h"
+
+#if ADB_HOST
+#include "usb_vendors.h"
+#endif
+
+#ifdef HAVE_BIG_ENDIAN
+#define H4(x)	(((x) & 0xFF000000) >> 24) | (((x) & 0x00FF0000) >> 8) | (((x) & 0x0000FF00) << 8) | (((x) & 0x000000FF) << 24)
+static inline void fix_endians(apacket *p)
+{
+    p->msg.command     = H4(p->msg.command);
+    p->msg.arg0        = H4(p->msg.arg0);
+    p->msg.arg1        = H4(p->msg.arg1);
+    p->msg.data_length = H4(p->msg.data_length);
+    p->msg.data_check  = H4(p->msg.data_check);
+    p->msg.magic       = H4(p->msg.magic);
+}
+unsigned host_to_le32(unsigned n)
+{
+    return H4(n);
+}
+#else
+#define fix_endians(p) do {} while (0)
+unsigned host_to_le32(unsigned n)
+{
+    return n;
+}
+#endif
+
+static int remote_read(apacket *p, atransport *t)
+{
+    if(usb_read(t->usb, &p->msg, sizeof(amessage))){
+        D("remote usb: read terminated (message)\n");
+        return -1;
+    }
+
+    fix_endians(p);
+
+    if(check_header(p)) {
+        D("remote usb: check_header failed\n");
+        return -1;
+    }
+
+    if(p->msg.data_length) {
+        if(usb_read(t->usb, p->data, p->msg.data_length)){
+            D("remote usb: terminated (data)\n");
+            return -1;
+        }
+    }
+
+    if(check_data(p)) {
+        D("remote usb: check_data failed\n");
+        return -1;
+    }
+
+    return 0;
+}
+
+static int remote_write(apacket *p, atransport *t)
+{
+    unsigned size = p->msg.data_length;
+
+    fix_endians(p);
+
+    if(usb_write(t->usb, &p->msg, sizeof(amessage))) {
+        D("remote usb: 1 - write terminated\n");
+        return -1;
+    }
+    if(p->msg.data_length == 0) return 0;
+    if(usb_write(t->usb, &p->data, size)) {
+        D("remote usb: 2 - write terminated\n");
+        return -1;
+    }
+
+    return 0;
+}
+
+static void remote_close(atransport *t)
+{
+    usb_close(t->usb);
+    t->usb = 0;
+}
+
+static void remote_kick(atransport *t)
+{
+    usb_kick(t->usb);
+}
+
+void init_usb_transport(atransport *t, usb_handle *h, int state)
+{
+    D("transport: usb\n");
+    t->close = remote_close;
+    t->kick = remote_kick;
+    t->read_from_remote = remote_read;
+    t->write_to_remote = remote_write;
+    t->sync_token = 1;
+    t->connection_state = state;
+    t->type = kTransportUsb;
+    t->usb = h;
+
+#if ADB_HOST
+    HOST = 1;
+#else
+    HOST = 0;
+#endif
+}
+
+#if ADB_HOST
+int is_adb_interface(int vid, int pid, int usb_class, int usb_subclass, int usb_protocol)
+{
+    unsigned i;
+    for (i = 0; i < vendorIdCount; i++) {
+        if (vid == vendorIds[i]) {
+            if (usb_class == ADB_CLASS && usb_subclass == ADB_SUBCLASS &&
+                    usb_protocol == ADB_PROTOCOL) {
+                return 1;
+            }
+
+            return 0;
+        }
+    }
+
+    return 0;
+}
+#endif
diff --git a/package/utils/adbd/src/adb/usb_libusb.c b/package/utils/adbd/src/adb/usb_libusb.c
new file mode 100644
index 0000000..06ff5dc
--- /dev/null
+++ b/package/utils/adbd/src/adb/usb_libusb.c
@@ -0,0 +1,657 @@
+/* 
+ * Copyright (C) 2009 bsdroid project
+ *               Alexey Tarasov <tarasov@dodologics.com>
+ *   
+ * 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 <sys/endian.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/uio.h>
+
+#include <err.h>
+#include <errno.h>
+#include <poll.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+#include <libusb.h>
+#include "sysdeps.h"
+
+#define   TRACE_TAG  TRACE_USB
+#include "adb.h"
+
+static adb_mutex_t usb_lock = ADB_MUTEX_INITIALIZER;
+static libusb_context *ctx = NULL;
+
+struct usb_handle
+{
+    usb_handle            *prev;
+    usb_handle            *next;
+
+    libusb_device         *dev;
+    libusb_device_handle  *devh;
+    int                   interface;
+    uint8_t               dev_bus;
+    uint8_t               dev_addr;
+	
+    int                   zero_mask;
+    unsigned char         end_point_address[2];
+    char                  serial[128];
+    
+    adb_cond_t            notify;
+    adb_mutex_t           lock;
+};
+
+static struct usb_handle handle_list = {
+        .prev = &handle_list,
+        .next = &handle_list,
+};
+
+void
+usb_cleanup()
+{
+	libusb_exit(ctx);
+}
+
+void
+report_bulk_libusb_error(int r)
+{
+    switch (r) {
+    case LIBUSB_ERROR_TIMEOUT:
+        D("Transfer timeout\n");
+        break;
+
+    case LIBUSB_ERROR_PIPE:
+        D("Control request is not supported\n");
+        break;
+
+    case LIBUSB_ERROR_OVERFLOW:
+        D("Device offered more data\n");
+        break;
+
+    case LIBUSB_ERROR_NO_DEVICE :
+        D("Device was disconnected\n");
+        break;
+
+    default:
+        D("Error %d during transfer\n", r);
+        break;
+    };
+}
+
+static int
+usb_bulk_write(usb_handle *uh, const void *data, int len)
+{
+    int r = 0;
+    int transferred = 0;
+
+    r = libusb_bulk_transfer(uh->devh, uh->end_point_address[1], (void *)data, len,
+                             &transferred, 0);
+   
+    if (r != 0) {
+        D("usb_bulk_write(): ");
+        report_bulk_libusb_error(r);
+        return r;
+    }
+   
+    return (transferred);
+}
+
+static int
+usb_bulk_read(usb_handle *uh, void *data, int len)
+{
+    int r = 0;
+    int transferred = 0;
+
+    r = libusb_bulk_transfer(uh->devh, uh->end_point_address[0], data, len,
+                             &transferred, 0);
+
+    if (r != 0) {
+        D("usb_bulk_read(): ");
+        report_bulk_libusb_error(r);
+        return r;
+    }
+   
+    return (transferred);
+}
+
+int
+usb_write(struct usb_handle *uh, const void *_data, int len)
+{
+    unsigned char *data = (unsigned char*) _data;
+    int n;
+    int need_zero = 0;
+
+    if (uh->zero_mask == 1) {
+        if (!(len & uh->zero_mask)) {
+            need_zero = 1;
+        }
+    }
+
+    D("usb_write(): %p:%d -> transport %p\n", _data, len, uh);
+    
+    while (len > 0) {
+        int xfer = (len > 4096) ? 4096 : len;
+
+        n = usb_bulk_write(uh, data, xfer);
+        
+        if (n != xfer) {
+            D("usb_write(): failed for transport %p (%d bytes left)\n", uh, len);
+            return -1;
+        }
+
+        len -= xfer;
+        data += xfer;
+    }
+
+    if (need_zero){
+        n = usb_bulk_write(uh, _data, 0);
+        
+        if (n < 0) {
+            D("usb_write(): failed to finish operation for transport %p\n", uh);
+        }
+        return n;
+    }
+
+    return 0;
+}
+
+int
+usb_read(struct usb_handle *uh, void *_data, int len)
+{
+    unsigned char *data = (unsigned char*) _data;
+    int n;
+
+    D("usb_read(): %p:%d <- transport %p\n", _data, len, uh);
+    
+    while (len > 0) {
+        int xfer = (len > 4096) ? 4096 : len;
+
+        n = usb_bulk_read(uh, data, xfer);
+        
+        if (n != xfer) {
+            if (n > 0) {
+                data += n;
+                len -= n;
+                continue;
+            }
+            
+            D("usb_read(): failed for transport %p (%d bytes left)\n", uh, len);
+            return -1;
+        }
+
+        len -= xfer;
+        data += xfer;
+    }
+
+    return 0;
+ }
+
+int
+usb_close(struct usb_handle *h)
+{
+    D("usb_close(): closing transport %p\n", h);
+    adb_mutex_lock(&usb_lock);
+    
+    h->next->prev = h->prev;
+    h->prev->next = h->next;
+    h->prev = NULL;
+    h->next = NULL;
+
+    libusb_release_interface(h->devh, h->interface);
+    libusb_close(h->devh);
+    libusb_unref_device(h->dev);
+    
+    adb_mutex_unlock(&usb_lock);
+
+    free(h);
+
+    return (0);
+}
+
+void usb_kick(struct usb_handle *h)
+{
+    D("usb_cick(): kicking transport %p\n", h);
+    
+    adb_mutex_lock(&h->lock);
+    unregister_usb_transport(h);
+    adb_mutex_unlock(&h->lock);
+    
+    h->next->prev = h->prev;
+    h->prev->next = h->next;
+    h->prev = NULL;
+    h->next = NULL;
+
+    libusb_release_interface(h->devh, h->interface);
+    libusb_close(h->devh);
+    libusb_unref_device(h->dev);
+    free(h);
+}
+
+int
+check_usb_interface(libusb_interface *interface,
+                    libusb_device_descriptor *desc,
+                    struct usb_handle *uh)
+{    
+    int e;
+    
+    if (interface->num_altsetting == 0) {
+        D("check_usb_interface(): No interface settings\n");
+        return -1;
+    }
+    
+    libusb_interface_descriptor *idesc = &interface->altsetting[0];
+    
+    if (idesc->bNumEndpoints != 2) {
+        D("check_usb_interface(): Interface have not 2 endpoints, ignoring\n");
+        return -1;
+    }
+
+    for (e = 0; e < idesc->bNumEndpoints; e++) {
+        libusb_endpoint_descriptor *edesc = &idesc->endpoint[e];
+        
+        if (edesc->bmAttributes != LIBUSB_TRANSFER_TYPE_BULK) {
+            D("check_usb_interface(): Endpoint (%u) is not bulk (%u), ignoring\n",
+                    edesc->bmAttributes, LIBUSB_TRANSFER_TYPE_BULK);
+            return -1;
+        }
+        
+        if (edesc->bEndpointAddress & LIBUSB_ENDPOINT_IN)
+            uh->end_point_address[0] = edesc->bEndpointAddress;
+        else
+            uh->end_point_address[1] = edesc->bEndpointAddress;
+        
+            /* aproto 01 needs 0 termination */
+        if (idesc->bInterfaceProtocol == 0x01) {
+            uh->zero_mask = edesc->wMaxPacketSize - 1;
+            D("check_usb_interface(): Forced Android interface protocol v.1\n");
+        }
+    }
+
+    D("check_usb_interface(): Device: %04x:%04x "
+      "iclass: %x, isclass: %x, iproto: %x ep: %x/%x-> ",
+        desc->idVendor, desc->idProduct, idesc->bInterfaceClass,
+	idesc->bInterfaceSubClass, idesc->bInterfaceProtocol,
+	uh->end_point_address[0], uh->end_point_address[1]);
+    
+    if (!is_adb_interface(desc->idVendor, desc->idProduct,
+            idesc->bInterfaceClass, idesc->bInterfaceSubClass,
+            idesc->bInterfaceProtocol))
+    {
+        D("not matches\n");
+        return -1;
+    }
+
+    D("matches\n");
+    return 1;
+}
+
+int
+check_usb_interfaces(libusb_config_descriptor *config,
+                     libusb_device_descriptor *desc, struct usb_handle *uh)
+{  
+    int i;
+    
+    for (i = 0; i < config->bNumInterfaces; ++i) {
+        if (check_usb_interface(&config->interface[i], desc, uh) != -1) {
+            /* found some interface and saved information about it */
+            D("check_usb_interfaces(): Interface %d of %04x:%04x "
+              "matches Android device\n", i, desc->idVendor,
+	      desc->idProduct);
+            
+            return  i;
+        }
+    }
+    
+    return -1;
+}
+
+int
+register_device(struct usb_handle *uh, const char *serial)
+{
+    D("register_device(): Registering %p [%s] as USB transport\n",
+       uh, serial);
+
+    struct usb_handle *usb= NULL;
+
+    usb = calloc(1, sizeof(struct usb_handle));
+    memcpy(usb, uh, sizeof(struct usb_handle));
+    strcpy(usb->serial, uh->serial);
+
+    adb_cond_init(&usb->notify, 0);
+    adb_mutex_init(&usb->lock, 0);
+
+    adb_mutex_lock(&usb_lock);
+    
+    usb->next = &handle_list;
+    usb->prev = handle_list.prev;
+    usb->prev->next = usb;
+    usb->next->prev = usb;
+
+    adb_mutex_unlock(&usb_lock);
+
+    register_usb_transport(usb, serial, NULL, 1); 
+
+    return (1);
+}
+
+int
+already_registered(usb_handle *uh)
+{
+    struct usb_handle *usb= NULL;
+    int exists = 0;
+    
+    adb_mutex_lock(&usb_lock);
+
+    for (usb = handle_list.next; usb != &handle_list; usb = usb->next) {
+        if ((usb->dev_bus == uh->dev_bus) &&
+            (usb->dev_addr == uh->dev_addr))
+        {
+            exists = 1;
+            break;
+        }
+    }
+
+    adb_mutex_unlock(&usb_lock);
+
+    return exists;
+}
+
+void
+check_device(libusb_device *dev) 
+{
+    struct usb_handle uh;
+    int i = 0;
+    int found = -1;
+    char serial[256] = {0};
+
+    libusb_device_descriptor desc;
+    libusb_config_descriptor *config = NULL;
+    
+    int r = libusb_get_device_descriptor(dev, &desc);
+
+    if (r != LIBUSB_SUCCESS) {
+        D("check_device(): Failed to get device descriptor\n");
+        return;
+    }
+    
+    if ((desc.idVendor == 0) && (desc.idProduct == 0))
+        return;
+    
+    D("check_device(): Probing usb device %04x:%04x\n",
+        desc.idVendor, desc.idProduct);
+    
+    if (!is_adb_interface (desc.idVendor, desc.idProduct,
+                           ADB_CLASS, ADB_SUBCLASS, ADB_PROTOCOL))
+    {
+        D("check_device(): Ignored due unknown vendor id\n");
+        return;
+    }
+    
+    uh.dev_bus = libusb_get_bus_number(dev);
+    uh.dev_addr = libusb_get_device_address(dev);
+    
+    if (already_registered(&uh)) {
+        D("check_device(): Device (bus: %d, address: %d) "
+          "is already registered\n", uh.dev_bus, uh.dev_addr);
+        return;
+    }
+    
+    D("check_device(): Device bus: %d, address: %d\n",
+        uh.dev_bus, uh.dev_addr);
+
+    r = libusb_get_active_config_descriptor(dev, &config);
+    
+    if (r != 0) {
+        if (r == LIBUSB_ERROR_NOT_FOUND) {
+            D("check_device(): Device %4x:%4x is unconfigured\n", 
+                desc.idVendor, desc.idProduct);
+            return;
+        }
+        
+        D("check_device(): Failed to get configuration for %4x:%4x\n",
+            desc.idVendor, desc.idProduct);
+        return;
+    }
+    
+    if (config == NULL) {
+        D("check_device(): Sanity check failed after "
+          "getting active config\n");
+        return;
+    }
+    
+    if (config->interface != NULL) {
+        found = check_usb_interfaces(config, &desc, &uh);
+    }
+    
+    /* not needed anymore */
+    libusb_free_config_descriptor(config);
+    
+    r = libusb_open(dev, &uh.devh);
+    uh.dev = dev;
+
+    if (r != 0) {
+        switch (r) {
+            case LIBUSB_ERROR_NO_MEM:
+                D("check_device(): Memory allocation problem\n");
+                break;
+                
+            case LIBUSB_ERROR_ACCESS:
+                D("check_device(): Permissions problem, "
+                  "current user priveleges are messed up?\n");
+                break;
+                
+            case LIBUSB_ERROR_NO_DEVICE:
+                D("check_device(): Device disconected, bad cable?\n");
+                break;
+            
+            default:
+                D("check_device(): libusb triggered error %d\n", r);
+        }
+        // skip rest
+        found = -1;
+    }
+    
+    if (found >= 0) {
+        D("check_device(): Device matches Android interface\n");
+        // read the device's serial number
+        memset(serial, 0, sizeof(serial));
+        uh.interface = found;
+        
+        r = libusb_claim_interface(uh.devh, uh.interface);
+        
+        if (r < 0) {
+            D("check_device(): Failed to claim interface %d\n",
+                uh.interface);
+
+            goto fail;
+        }
+
+        if (desc.iSerialNumber) {
+            // reading serial
+            uint16_t    buffer[128] = {0};
+            uint16_t    languages[128] = {0};
+            int languageCount = 0;
+
+            memset(languages, 0, sizeof(languages));
+            r = libusb_control_transfer(uh.devh, 
+                LIBUSB_ENDPOINT_IN |  LIBUSB_REQUEST_TYPE_STANDARD | LIBUSB_RECIPIENT_DEVICE,
+                LIBUSB_REQUEST_GET_DESCRIPTOR, LIBUSB_DT_STRING << 8,
+		0, (uint8_t *)languages, sizeof(languages), 0);
+
+            if (r <= 0) {
+                D("check_device(): Failed to get languages count\n");
+                goto fail;
+            } 
+            
+            languageCount = (r - 2) / 2;
+            
+            for (i = 1; i <= languageCount; ++i) {
+                memset(buffer, 0, sizeof(buffer));
+
+                r = libusb_control_transfer(uh.devh, 
+                    LIBUSB_ENDPOINT_IN |  LIBUSB_REQUEST_TYPE_STANDARD | LIBUSB_RECIPIENT_DEVICE,
+                    LIBUSB_REQUEST_GET_DESCRIPTOR, (LIBUSB_DT_STRING << 8) | desc.iSerialNumber,
+		    languages[i], (uint8_t *)buffer, sizeof(buffer), 0);
+            
+                if (r > 0) { /* converting serial */
+                    int j = 0;
+                    r /= 2;
+                
+                    for (j = 1; j < r; ++j)
+                        serial[j - 1] = buffer[j];
+                
+                    serial[j - 1] = '\0';
+                    break; /* languagesCount cycle */
+                }
+            }
+            
+            if (register_device(&uh, serial) == 0) {
+                D("check_device(): Failed to register device\n");
+                goto fail_interface;
+            }
+            
+            libusb_ref_device(dev);
+        }
+    }
+    
+    return;
+
+fail_interface:
+    libusb_release_interface(uh.devh, uh.interface);
+
+fail:
+    libusb_close(uh.devh);
+    uh.devh = NULL;
+}
+
+int
+check_device_connected(struct usb_handle *uh)
+{
+    int r = libusb_kernel_driver_active(uh->devh, uh->interface);
+    
+    if (r == LIBUSB_ERROR_NO_DEVICE)
+        return 0;
+    
+    if (r < 0)
+        return -1;
+    
+    return 1;
+}
+
+void
+kick_disconnected()
+{
+    struct usb_handle *usb= NULL;
+    
+    adb_mutex_lock(&usb_lock);
+
+    for (usb = handle_list.next; usb != &handle_list; usb = usb->next) {
+        
+        if (check_device_connected(usb) == 0) {
+            D("kick_disconnected(): Transport %p is not online anymore\n",
+                usb);
+
+            usb_kick(usb);
+        }
+    }
+    
+    adb_mutex_unlock(&usb_lock);
+}
+
+void
+scan_usb_devices()
+{
+    D("scan_usb_devices(): started\n");
+    
+    libusb_device **devs= NULL;
+    libusb_device *dev= NULL;
+    ssize_t cnt = libusb_get_device_list(ctx, &devs);
+
+    if (cnt < 0) {
+        D("scan_usb_devices(): Failed to get device list (error: %d)\n",
+            cnt);
+
+        return;
+    }
+    
+    int i = 0;
+
+    while ((dev = devs[i++]) != NULL) {
+        check_device(dev);
+    }
+
+    libusb_free_device_list(devs, 1);
+}
+
+void *
+device_poll_thread(void* unused)
+{
+    D("device_poll_thread(): Created USB scan thread\n");
+    
+    for (;;) {
+        sleep(5);
+        kick_disconnected();
+        scan_usb_devices();
+    }
+
+    /* never reaching this point */
+    return (NULL);
+}
+
+static void
+sigalrm_handler(int signo)
+{
+    /* nothing */
+}
+
+void
+usb_init()
+{
+    D("usb_init(): started\n");
+    adb_thread_t        tid;
+    struct sigaction actions;
+
+    int r = libusb_init(&ctx);
+
+    if (r != LIBUSB_SUCCESS) {
+        err(EX_IOERR, "Failed to init libusb\n");
+    }
+
+    memset(&actions, 0, sizeof(actions));
+    
+    sigemptyset(&actions.sa_mask);
+    
+    actions.sa_flags = 0;
+    actions.sa_handler = sigalrm_handler;
+    
+    sigaction(SIGALRM, &actions, NULL);
+
+	/* initial device scan */
+	scan_usb_devices();
+	
+	/* starting USB event polling thread */
+    if (adb_thread_create(&tid, device_poll_thread, NULL)) {
+            err(EX_IOERR, "cannot create USB scan thread\n");
+    }
+    
+    D("usb_init(): finished\n");
+}
+
diff --git a/package/utils/adbd/src/adb/usb_linux.c b/package/utils/adbd/src/adb/usb_linux.c
new file mode 100644
index 0000000..8ff753e
--- /dev/null
+++ b/package/utils/adbd/src/adb/usb_linux.c
@@ -0,0 +1,715 @@
+/*
+ * 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 <unistd.h>
+#include <string.h>
+
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <ctype.h>
+
+#include <linux/usbdevice_fs.h>
+#include <linux/version.h>
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 20)
+#include <linux/usb/ch9.h>
+#else
+#include <linux/usb_ch9.h>
+#endif
+#include <asm/byteorder.h>
+
+#include "sysdeps.h"
+
+#define   TRACE_TAG  TRACE_USB
+#include "adb.h"
+
+
+/* usb scan debugging is waaaay too verbose */
+#define DBGX(x...)
+
+ADB_MUTEX_DEFINE( usb_lock );
+
+struct usb_handle
+{
+    usb_handle *prev;
+    usb_handle *next;
+
+    char fname[64];
+    int desc;
+    unsigned char ep_in;
+    unsigned char ep_out;
+
+    unsigned zero_mask;
+    unsigned writeable;
+
+    struct usbdevfs_urb urb_in;
+    struct usbdevfs_urb urb_out;
+
+    int urb_in_busy;
+    int urb_out_busy;
+    int dead;
+
+    adb_cond_t notify;
+    adb_mutex_t lock;
+
+    // for garbage collecting disconnected devices
+    int mark;
+
+    // ID of thread currently in REAPURB
+    pthread_t reaper_thread;
+};
+
+static usb_handle handle_list = {
+    .prev = &handle_list,
+    .next = &handle_list,
+};
+
+static int known_device(const char *dev_name)
+{
+    usb_handle *usb;
+
+    adb_mutex_lock(&usb_lock);
+    for(usb = handle_list.next; usb != &handle_list; usb = usb->next){
+        if(!strcmp(usb->fname, dev_name)) {
+            // set mark flag to indicate this device is still alive
+            usb->mark = 1;
+            adb_mutex_unlock(&usb_lock);
+            return 1;
+        }
+    }
+    adb_mutex_unlock(&usb_lock);
+    return 0;
+}
+
+static void kick_disconnected_devices()
+{
+    usb_handle *usb;
+
+    adb_mutex_lock(&usb_lock);
+    // kick any devices in the device list that were not found in the device scan
+    for(usb = handle_list.next; usb != &handle_list; usb = usb->next){
+        if (usb->mark == 0) {
+            usb_kick(usb);
+        } else {
+            usb->mark = 0;
+        }
+    }
+    adb_mutex_unlock(&usb_lock);
+
+}
+
+static void register_device(const char *dev_name, const char *devpath,
+                            unsigned char ep_in, unsigned char ep_out,
+                            int ifc, int serial_index, unsigned zero_mask);
+
+static inline int badname(const char *name)
+{
+    while(*name) {
+        if(!isdigit(*name++)) return 1;
+    }
+    return 0;
+}
+
+static void find_usb_device(const char *base,
+        void (*register_device_callback)
+                (const char *, const char *, unsigned char, unsigned char, int, int, unsigned))
+{
+    char busname[32], devname[32];
+    unsigned char local_ep_in, local_ep_out;
+    DIR *busdir , *devdir ;
+    struct dirent *de;
+    int fd ;
+
+    busdir = opendir(base);
+    if(busdir == 0) return;
+
+    while((de = readdir(busdir)) != 0) {
+        if(badname(de->d_name)) continue;
+
+        snprintf(busname, sizeof busname, "%s/%s", base, de->d_name);
+        devdir = opendir(busname);
+        if(devdir == 0) continue;
+
+//        DBGX("[ scanning %s ]\n", busname);
+        while((de = readdir(devdir))) {
+            unsigned char devdesc[4096];
+            unsigned char* bufptr = devdesc;
+            unsigned char* bufend;
+            struct usb_device_descriptor* device;
+            struct usb_config_descriptor* config;
+            struct usb_interface_descriptor* interface;
+            struct usb_endpoint_descriptor *ep1, *ep2;
+            unsigned zero_mask = 0;
+            unsigned vid, pid;
+            size_t desclength;
+
+            if(badname(de->d_name)) continue;
+            snprintf(devname, sizeof devname, "%s/%s", busname, de->d_name);
+
+            if(known_device(devname)) {
+                DBGX("skipping %s\n", devname);
+                continue;
+            }
+
+//            DBGX("[ scanning %s ]\n", devname);
+            if((fd = unix_open(devname, O_RDONLY)) < 0) {
+                continue;
+            }
+
+            desclength = adb_read(fd, devdesc, sizeof(devdesc));
+            bufend = bufptr + desclength;
+
+                // should have device and configuration descriptors, and atleast two endpoints
+            if (desclength < USB_DT_DEVICE_SIZE + USB_DT_CONFIG_SIZE) {
+                D("desclength %zu is too small\n", desclength);
+                adb_close(fd);
+                continue;
+            }
+
+            device = (struct usb_device_descriptor*)bufptr;
+            bufptr += USB_DT_DEVICE_SIZE;
+
+            if((device->bLength != USB_DT_DEVICE_SIZE) || (device->bDescriptorType != USB_DT_DEVICE)) {
+                adb_close(fd);
+                continue;
+            }
+
+            vid = device->idVendor;
+            pid = device->idProduct;
+            DBGX("[ %s is V:%04x P:%04x ]\n", devname, vid, pid);
+
+                // should have config descriptor next
+            config = (struct usb_config_descriptor *)bufptr;
+            bufptr += USB_DT_CONFIG_SIZE;
+            if (config->bLength != USB_DT_CONFIG_SIZE || config->bDescriptorType != USB_DT_CONFIG) {
+                D("usb_config_descriptor not found\n");
+                adb_close(fd);
+                continue;
+            }
+
+                // loop through all the descriptors and look for the ADB interface
+            while (bufptr < bufend) {
+                unsigned char length = bufptr[0];
+                unsigned char type = bufptr[1];
+
+                if (type == USB_DT_INTERFACE) {
+                    interface = (struct usb_interface_descriptor *)bufptr;
+                    bufptr += length;
+
+                    if (length != USB_DT_INTERFACE_SIZE) {
+                        D("interface descriptor has wrong size\n");
+                        break;
+                    }
+
+                    DBGX("bInterfaceClass: %d,  bInterfaceSubClass: %d,"
+                         "bInterfaceProtocol: %d, bNumEndpoints: %d\n",
+                         interface->bInterfaceClass, interface->bInterfaceSubClass,
+                         interface->bInterfaceProtocol, interface->bNumEndpoints);
+
+                    if (interface->bNumEndpoints == 2 &&
+                            is_adb_interface(vid, pid, interface->bInterfaceClass,
+                            interface->bInterfaceSubClass, interface->bInterfaceProtocol))  {
+
+                        struct stat st;
+                        char pathbuf[128];
+                        char link[256];
+                        char *devpath = NULL;
+
+                        DBGX("looking for bulk endpoints\n");
+                            // looks like ADB...
+                        ep1 = (struct usb_endpoint_descriptor *)bufptr;
+                        bufptr += USB_DT_ENDPOINT_SIZE;
+                        ep2 = (struct usb_endpoint_descriptor *)bufptr;
+                        bufptr += USB_DT_ENDPOINT_SIZE;
+
+                        if (bufptr > devdesc + desclength ||
+                            ep1->bLength != USB_DT_ENDPOINT_SIZE ||
+                            ep1->bDescriptorType != USB_DT_ENDPOINT ||
+                            ep2->bLength != USB_DT_ENDPOINT_SIZE ||
+                            ep2->bDescriptorType != USB_DT_ENDPOINT) {
+                            D("endpoints not found\n");
+                            break;
+                        }
+
+                            // both endpoints should be bulk
+                        if (ep1->bmAttributes != USB_ENDPOINT_XFER_BULK ||
+                            ep2->bmAttributes != USB_ENDPOINT_XFER_BULK) {
+                            D("bulk endpoints not found\n");
+                            continue;
+                        }
+                            /* aproto 01 needs 0 termination */
+                        if(interface->bInterfaceProtocol == 0x01) {
+                            zero_mask = ep1->wMaxPacketSize - 1;
+                        }
+
+                            // we have a match.  now we just need to figure out which is in and which is out.
+                        if (ep1->bEndpointAddress & USB_ENDPOINT_DIR_MASK) {
+                            local_ep_in = ep1->bEndpointAddress;
+                            local_ep_out = ep2->bEndpointAddress;
+                        } else {
+                            local_ep_in = ep2->bEndpointAddress;
+                            local_ep_out = ep1->bEndpointAddress;
+                        }
+
+                            // Determine the device path
+                        if (!fstat(fd, &st) && S_ISCHR(st.st_mode)) {
+                            char *slash;
+                            ssize_t link_len;
+                            snprintf(pathbuf, sizeof(pathbuf), "/sys/dev/char/%d:%d",
+                                     major(st.st_rdev), minor(st.st_rdev));
+                            link_len = readlink(pathbuf, link, sizeof(link) - 1);
+                            if (link_len > 0) {
+                                link[link_len] = '\0';
+                                slash = strrchr(link, '/');
+                                if (slash) {
+                                    snprintf(pathbuf, sizeof(pathbuf),
+                                             "usb:%s", slash + 1);
+                                    devpath = pathbuf;
+                                }
+                            }
+                        }
+
+                        register_device_callback(devname, devpath,
+                                local_ep_in, local_ep_out,
+                                interface->bInterfaceNumber, device->iSerialNumber, zero_mask);
+                        break;
+                    }
+                } else {
+                    bufptr += length;
+                }
+            } // end of while
+
+            adb_close(fd);
+        } // end of devdir while
+        closedir(devdir);
+    } //end of busdir while
+    closedir(busdir);
+}
+
+void usb_cleanup()
+{
+}
+
+static int usb_bulk_write(usb_handle *h, const void *data, int len)
+{
+    struct usbdevfs_urb *urb = &h->urb_out;
+    int res;
+    struct timeval tv;
+    struct timespec ts;
+
+    memset(urb, 0, sizeof(*urb));
+    urb->type = USBDEVFS_URB_TYPE_BULK;
+    urb->endpoint = h->ep_out;
+    urb->status = -1;
+    urb->buffer = (void*) data;
+    urb->buffer_length = len;
+
+    D("++ write ++\n");
+
+    adb_mutex_lock(&h->lock);
+    if(h->dead) {
+        res = -1;
+        goto fail;
+    }
+    do {
+        res = ioctl(h->desc, USBDEVFS_SUBMITURB, urb);
+    } while((res < 0) && (errno == EINTR));
+
+    if(res < 0) {
+        goto fail;
+    }
+
+    res = -1;
+    h->urb_out_busy = 1;
+    for(;;) {
+        /* time out after five seconds */
+        gettimeofday(&tv, NULL);
+        ts.tv_sec = tv.tv_sec + 5;
+        ts.tv_nsec = tv.tv_usec * 1000L;
+        res = pthread_cond_timedwait(&h->notify, &h->lock, &ts);
+        if(res < 0 || h->dead) {
+            break;
+        }
+        if(h->urb_out_busy == 0) {
+            if(urb->status == 0) {
+                res = urb->actual_length;
+            }
+            break;
+        }
+    }
+fail:
+    adb_mutex_unlock(&h->lock);
+    D("-- write --\n");
+    return res;
+}
+
+static int usb_bulk_read(usb_handle *h, void *data, int len)
+{
+    struct usbdevfs_urb *urb = &h->urb_in;
+    struct usbdevfs_urb *out = NULL;
+    int res;
+
+    memset(urb, 0, sizeof(*urb));
+    urb->type = USBDEVFS_URB_TYPE_BULK;
+    urb->endpoint = h->ep_in;
+    urb->status = -1;
+    urb->buffer = data;
+    urb->buffer_length = len;
+
+
+    adb_mutex_lock(&h->lock);
+    if(h->dead) {
+        res = -1;
+        goto fail;
+    }
+    do {
+        res = ioctl(h->desc, USBDEVFS_SUBMITURB, urb);
+    } while((res < 0) && (errno == EINTR));
+
+    if(res < 0) {
+        goto fail;
+    }
+
+    h->urb_in_busy = 1;
+    for(;;) {
+        D("[ reap urb - wait ]\n");
+        h->reaper_thread = pthread_self();
+        adb_mutex_unlock(&h->lock);
+        res = ioctl(h->desc, USBDEVFS_REAPURB, &out);
+        int saved_errno = errno;
+        adb_mutex_lock(&h->lock);
+        h->reaper_thread = 0;
+        if(h->dead) {
+            res = -1;
+            break;
+        }
+        if(res < 0) {
+            if(saved_errno == EINTR) {
+                continue;
+            }
+            D("[ reap urb - error ]\n");
+            break;
+        }
+        D("[ urb @%p status = %d, actual = %d ]\n",
+            out, out->status, out->actual_length);
+
+        if(out == &h->urb_in) {
+            D("[ reap urb - IN complete ]\n");
+            h->urb_in_busy = 0;
+            if(urb->status == 0) {
+                res = urb->actual_length;
+            } else {
+                res = -1;
+            }
+            break;
+        }
+        if(out == &h->urb_out) {
+            D("[ reap urb - OUT compelete ]\n");
+            h->urb_out_busy = 0;
+            adb_cond_broadcast(&h->notify);
+        }
+    }
+fail:
+    adb_mutex_unlock(&h->lock);
+    return res;
+}
+
+
+int usb_write(usb_handle *h, const void *_data, int len)
+{
+    unsigned char *data = (unsigned char*) _data;
+    int n;
+    int need_zero = 0;
+
+    if(h->zero_mask) {
+            /* if we need 0-markers and our transfer
+            ** is an even multiple of the packet size,
+            ** we make note of it
+            */
+        if(!(len & h->zero_mask)) {
+            need_zero = 1;
+        }
+    }
+
+    while(len > 0) {
+        int xfer = (len > 4096) ? 4096 : len;
+
+        n = usb_bulk_write(h, data, xfer);
+        if(n != xfer) {
+            D("ERROR: n = %d, errno = %d (%s)\n",
+                n, errno, strerror(errno));
+            return -1;
+        }
+
+        len -= xfer;
+        data += xfer;
+    }
+
+    if(need_zero){
+        n = usb_bulk_write(h, _data, 0);
+        return n;
+    }
+
+    return 0;
+}
+
+int usb_read(usb_handle *h, void *_data, int len)
+{
+    unsigned char *data = (unsigned char*) _data;
+    int n;
+
+    D("++ usb_read ++\n");
+    while(len > 0) {
+        int xfer = (len > 4096) ? 4096 : len;
+
+        D("[ usb read %d fd = %d], fname=%s\n", xfer, h->desc, h->fname);
+        n = usb_bulk_read(h, data, xfer);
+        D("[ usb read %d ] = %d, fname=%s\n", xfer, n, h->fname);
+        if(n != xfer) {
+            if((errno == ETIMEDOUT) && (h->desc != -1)) {
+                D("[ timeout ]\n");
+                if(n > 0){
+                    data += n;
+                    len -= n;
+                }
+                continue;
+            }
+            D("ERROR: n = %d, errno = %d (%s)\n",
+                n, errno, strerror(errno));
+            return -1;
+        }
+
+        len -= xfer;
+        data += xfer;
+    }
+
+    D("-- usb_read --\n");
+    return 0;
+}
+
+void usb_kick(usb_handle *h)
+{
+    D("[ kicking %p (fd = %d) ]\n", h, h->desc);
+    adb_mutex_lock(&h->lock);
+    if(h->dead == 0) {
+        h->dead = 1;
+
+        if (h->writeable) {
+            /* HACK ALERT!
+            ** Sometimes we get stuck in ioctl(USBDEVFS_REAPURB).
+            ** This is a workaround for that problem.
+            */
+            if (h->reaper_thread) {
+                pthread_kill(h->reaper_thread, SIGALRM);
+            }
+
+            /* cancel any pending transactions
+            ** these will quietly fail if the txns are not active,
+            ** but this ensures that a reader blocked on REAPURB
+            ** will get unblocked
+            */
+            ioctl(h->desc, USBDEVFS_DISCARDURB, &h->urb_in);
+            ioctl(h->desc, USBDEVFS_DISCARDURB, &h->urb_out);
+            h->urb_in.status = -ENODEV;
+            h->urb_out.status = -ENODEV;
+            h->urb_in_busy = 0;
+            h->urb_out_busy = 0;
+            adb_cond_broadcast(&h->notify);
+        } else {
+            unregister_usb_transport(h);
+        }
+    }
+    adb_mutex_unlock(&h->lock);
+}
+
+int usb_close(usb_handle *h)
+{
+    D("[ usb close ... ]\n");
+    adb_mutex_lock(&usb_lock);
+    h->next->prev = h->prev;
+    h->prev->next = h->next;
+    h->prev = 0;
+    h->next = 0;
+
+    adb_close(h->desc);
+    D("[ usb closed %p (fd = %d) ]\n", h, h->desc);
+    adb_mutex_unlock(&usb_lock);
+
+    free(h);
+    return 0;
+}
+
+static void register_device(const char *dev_name, const char *devpath,
+                            unsigned char ep_in, unsigned char ep_out,
+                            int interface, int serial_index, unsigned zero_mask)
+{
+    usb_handle* usb = 0;
+    int n = 0;
+    char serial[256];
+
+        /* Since Linux will not reassign the device ID (and dev_name)
+        ** as long as the device is open, we can add to the list here
+        ** once we open it and remove from the list when we're finally
+        ** closed and everything will work out fine.
+        **
+        ** If we have a usb_handle on the list 'o handles with a matching
+        ** name, we have no further work to do.
+        */
+    adb_mutex_lock(&usb_lock);
+    for(usb = handle_list.next; usb != &handle_list; usb = usb->next){
+        if(!strcmp(usb->fname, dev_name)) {
+            adb_mutex_unlock(&usb_lock);
+            return;
+        }
+    }
+    adb_mutex_unlock(&usb_lock);
+
+    D("[ usb located new device %s (%d/%d/%d) ]\n",
+        dev_name, ep_in, ep_out, interface);
+    usb = calloc(1, sizeof(usb_handle));
+    strcpy(usb->fname, dev_name);
+    usb->ep_in = ep_in;
+    usb->ep_out = ep_out;
+    usb->zero_mask = zero_mask;
+    usb->writeable = 1;
+
+    adb_cond_init(&usb->notify, 0);
+    adb_mutex_init(&usb->lock, 0);
+    /* initialize mark to 1 so we don't get garbage collected after the device scan */
+    usb->mark = 1;
+    usb->reaper_thread = 0;
+
+    usb->desc = unix_open(usb->fname, O_RDWR);
+    if(usb->desc < 0) {
+        /* if we fail, see if have read-only access */
+        usb->desc = unix_open(usb->fname, O_RDONLY);
+        if(usb->desc < 0) goto fail;
+        usb->writeable = 0;
+        D("[ usb open read-only %s fd = %d]\n", usb->fname, usb->desc);
+    } else {
+        D("[ usb open %s fd = %d]\n", usb->fname, usb->desc);
+        n = ioctl(usb->desc, USBDEVFS_CLAIMINTERFACE, &interface);
+        if(n != 0) goto fail;
+    }
+
+        /* read the device's serial number */
+    serial[0] = 0;
+    memset(serial, 0, sizeof(serial));
+    if (serial_index) {
+        struct usbdevfs_ctrltransfer  ctrl;
+        __u16 buffer[128];
+        __u16 languages[128];
+        int i, result;
+        int languageCount = 0;
+
+        memset(languages, 0, sizeof(languages));
+        memset(&ctrl, 0, sizeof(ctrl));
+
+            // read list of supported languages
+        ctrl.bRequestType = USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE;
+        ctrl.bRequest = USB_REQ_GET_DESCRIPTOR;
+        ctrl.wValue = (USB_DT_STRING << 8) | 0;
+        ctrl.wIndex = 0;
+        ctrl.wLength = sizeof(languages);
+        ctrl.data = languages;
+        ctrl.timeout = 1000;
+
+        result = ioctl(usb->desc, USBDEVFS_CONTROL, &ctrl);
+        if (result > 0)
+            languageCount = (result - 2) / 2;
+
+        for (i = 1; i <= languageCount; i++) {
+            memset(buffer, 0, sizeof(buffer));
+            memset(&ctrl, 0, sizeof(ctrl));
+
+            ctrl.bRequestType = USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE;
+            ctrl.bRequest = USB_REQ_GET_DESCRIPTOR;
+            ctrl.wValue = (USB_DT_STRING << 8) | serial_index;
+            ctrl.wIndex = __le16_to_cpu(languages[i]);
+            ctrl.wLength = sizeof(buffer);
+            ctrl.data = buffer;
+            ctrl.timeout = 1000;
+
+            result = ioctl(usb->desc, USBDEVFS_CONTROL, &ctrl);
+            if (result > 0) {
+                int i;
+                // skip first word, and copy the rest to the serial string, changing shorts to bytes.
+                result /= 2;
+                for (i = 1; i < result; i++)
+                    serial[i - 1] = __le16_to_cpu(buffer[i]);
+                serial[i - 1] = 0;
+                break;
+            }
+        }
+    }
+
+        /* add to the end of the active handles */
+    adb_mutex_lock(&usb_lock);
+    usb->next = &handle_list;
+    usb->prev = handle_list.prev;
+    usb->prev->next = usb;
+    usb->next->prev = usb;
+    adb_mutex_unlock(&usb_lock);
+
+    register_usb_transport(usb, serial, devpath, usb->writeable);
+    return;
+
+fail:
+    D("[ usb open %s error=%d, err_str = %s]\n",
+        usb->fname,  errno, strerror(errno));
+    if(usb->desc >= 0) {
+        adb_close(usb->desc);
+    }
+    free(usb);
+}
+
+void* device_poll_thread(void* unused)
+{
+    D("Created device thread\n");
+    for(;;) {
+            /* XXX use inotify */
+        find_usb_device("/dev/bus/usb", register_device);
+        kick_disconnected_devices();
+        sleep(1);
+    }
+    return NULL;
+}
+
+static void sigalrm_handler(int signo)
+{
+    // don't need to do anything here
+}
+
+void usb_init()
+{
+    adb_thread_t tid;
+    struct sigaction    actions;
+
+    memset(&actions, 0, sizeof(actions));
+    sigemptyset(&actions.sa_mask);
+    actions.sa_flags = 0;
+    actions.sa_handler = sigalrm_handler;
+    sigaction(SIGALRM,& actions, NULL);
+
+    if(adb_thread_create(&tid, device_poll_thread, NULL)){
+        fatal_errno("cannot create input thread");
+    }
+}
diff --git a/package/utils/adbd/src/adb/usb_linux_client.c b/package/utils/adbd/src/adb/usb_linux_client.c
new file mode 100644
index 0000000..258f260
--- /dev/null
+++ b/package/utils/adbd/src/adb/usb_linux_client.c
@@ -0,0 +1,497 @@
+/*
+ * 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 <unistd.h>
+#include <string.h>
+
+#include <linux/usb/ch9.h>
+#include <linux/usb/functionfs.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <errno.h>
+#include <endian.h>
+#include "sysdeps.h"
+
+#define   TRACE_TAG  TRACE_USB
+#include "adb.h"
+
+#define MAX_PACKET_SIZE_FS	64
+#define MAX_PACKET_SIZE_HS	512
+
+#define cpu_to_le16(x)  (x)
+#define cpu_to_le32(x)  (x)
+
+struct usb_handle
+{
+    adb_cond_t notify;
+    adb_mutex_t lock;
+
+    int (*write)(usb_handle *h, const void *data, int len);
+    int (*read)(usb_handle *h, void *data, int len);
+    void (*kick)(usb_handle *h);
+
+    // Legacy f_adb
+    int fd;
+
+    // FunctionFS
+    int control;
+    int bulk_out; /* "out" from the host's perspective => source for adbd */
+    int bulk_in;  /* "in" from the host's perspective => sink for adbd */
+};
+
+static const struct {
+    struct usb_functionfs_descs_head header;
+    struct {
+        struct usb_interface_descriptor intf;
+        struct usb_endpoint_descriptor_no_audio source;
+        struct usb_endpoint_descriptor_no_audio sink;
+    } __attribute__((packed)) fs_descs, hs_descs;
+} __attribute__((packed)) descriptors = {
+    .header = {
+        .magic = cpu_to_le32(FUNCTIONFS_DESCRIPTORS_MAGIC),
+        .length = cpu_to_le32(sizeof(descriptors)),
+        .fs_count = 3,
+        .hs_count = 3,
+    },
+    .fs_descs = {
+        .intf = {
+            .bLength = sizeof(descriptors.fs_descs.intf),
+            .bDescriptorType = USB_DT_INTERFACE,
+            .bInterfaceNumber = 0,
+            .bNumEndpoints = 2,
+            .bInterfaceClass = ADB_CLASS,
+            .bInterfaceSubClass = ADB_SUBCLASS,
+            .bInterfaceProtocol = ADB_PROTOCOL,
+            .iInterface = 1, /* first string from the provided table */
+        },
+        .source = {
+            .bLength = sizeof(descriptors.fs_descs.source),
+            .bDescriptorType = USB_DT_ENDPOINT,
+            .bEndpointAddress = 1 | USB_DIR_OUT,
+            .bmAttributes = USB_ENDPOINT_XFER_BULK,
+            .wMaxPacketSize = MAX_PACKET_SIZE_FS,
+        },
+        .sink = {
+            .bLength = sizeof(descriptors.fs_descs.sink),
+            .bDescriptorType = USB_DT_ENDPOINT,
+            .bEndpointAddress = 2 | USB_DIR_IN,
+            .bmAttributes = USB_ENDPOINT_XFER_BULK,
+            .wMaxPacketSize = MAX_PACKET_SIZE_FS,
+        },
+    },
+    .hs_descs = {
+        .intf = {
+            .bLength = sizeof(descriptors.hs_descs.intf),
+            .bDescriptorType = USB_DT_INTERFACE,
+            .bInterfaceNumber = 0,
+            .bNumEndpoints = 2,
+            .bInterfaceClass = ADB_CLASS,
+            .bInterfaceSubClass = ADB_SUBCLASS,
+            .bInterfaceProtocol = ADB_PROTOCOL,
+            .iInterface = 1, /* first string from the provided table */
+        },
+        .source = {
+            .bLength = sizeof(descriptors.hs_descs.source),
+            .bDescriptorType = USB_DT_ENDPOINT,
+            .bEndpointAddress = 1 | USB_DIR_OUT,
+            .bmAttributes = USB_ENDPOINT_XFER_BULK,
+            .wMaxPacketSize = MAX_PACKET_SIZE_HS,
+        },
+        .sink = {
+            .bLength = sizeof(descriptors.hs_descs.sink),
+            .bDescriptorType = USB_DT_ENDPOINT,
+            .bEndpointAddress = 2 | USB_DIR_IN,
+            .bmAttributes = USB_ENDPOINT_XFER_BULK,
+            .wMaxPacketSize = MAX_PACKET_SIZE_HS,
+        },
+    },
+};
+
+#define STR_INTERFACE_ "ADB Interface"
+
+static const struct {
+    struct usb_functionfs_strings_head header;
+    struct {
+        __le16 code;
+        const char str1[sizeof(STR_INTERFACE_)];
+    } __attribute__((packed)) lang0;
+} __attribute__((packed)) strings = {
+    .header = {
+        .magic = cpu_to_le32(FUNCTIONFS_STRINGS_MAGIC),
+        .length = cpu_to_le32(sizeof(strings)),
+        .str_count = cpu_to_le32(1),
+        .lang_count = cpu_to_le32(1),
+    },
+    .lang0 = {
+        cpu_to_le16(0x0409), /* en-us */
+        STR_INTERFACE_,
+    },
+};
+
+
+
+static void *usb_adb_open_thread(void *x)
+{
+    struct usb_handle *usb = (struct usb_handle *)x;
+    int fd;
+
+    while (1) {
+        // wait until the USB device needs opening
+        adb_mutex_lock(&usb->lock);
+        while (usb->fd != -1)
+            adb_cond_wait(&usb->notify, &usb->lock);
+        adb_mutex_unlock(&usb->lock);
+
+        D("[ usb_thread - opening device ]\n");
+        do {
+            /* XXX use inotify? */
+            fd = unix_open("/dev/android_adb", O_RDWR);
+            if (fd < 0) {
+                // to support older kernels
+                fd = unix_open("/dev/android", O_RDWR);
+            }
+            if (fd < 0) {
+                adb_sleep_ms(1000);
+            }
+        } while (fd < 0);
+        D("[ opening device succeeded ]\n");
+
+        close_on_exec(fd);
+        usb->fd = fd;
+
+        D("[ usb_thread - registering device ]\n");
+        register_usb_transport(usb, 0, 0, 1);
+    }
+
+    // never gets here
+    return 0;
+}
+
+static int usb_adb_write(usb_handle *h, const void *data, int len)
+{
+    int n;
+
+    D("about to write (fd=%d, len=%d)\n", h->fd, len);
+    n = adb_write(h->fd, data, len);
+    if(n != len) {
+        D("ERROR: fd = %d, n = %d, errno = %d (%s)\n",
+            h->fd, n, errno, strerror(errno));
+        return -1;
+    }
+    D("[ done fd=%d ]\n", h->fd);
+    return 0;
+}
+
+static int usb_adb_read(usb_handle *h, void *data, int len)
+{
+    int n;
+
+    D("about to read (fd=%d, len=%d)\n", h->fd, len);
+    n = adb_read(h->fd, data, len);
+    if(n != len) {
+        D("ERROR: fd = %d, n = %d, errno = %d (%s)\n",
+            h->fd, n, errno, strerror(errno));
+        return -1;
+    }
+    D("[ done fd=%d ]\n", h->fd);
+    return 0;
+}
+
+static void usb_adb_kick(usb_handle *h)
+{
+    D("usb_kick\n");
+    adb_mutex_lock(&h->lock);
+    adb_close(h->fd);
+    h->fd = -1;
+
+    // notify usb_adb_open_thread that we are disconnected
+    adb_cond_signal(&h->notify);
+    adb_mutex_unlock(&h->lock);
+}
+
+static void usb_adb_init()
+{
+    usb_handle *h;
+    adb_thread_t tid;
+    int fd;
+
+    h = calloc(1, sizeof(usb_handle));
+
+    h->write = usb_adb_write;
+    h->read = usb_adb_read;
+    h->kick = usb_adb_kick;
+    h->fd = -1;
+
+    adb_cond_init(&h->notify, 0);
+    adb_mutex_init(&h->lock, 0);
+
+    // Open the file /dev/android_adb_enable to trigger 
+    // the enabling of the adb USB function in the kernel.
+    // We never touch this file again - just leave it open
+    // indefinitely so the kernel will know when we are running
+    // and when we are not.
+    fd = unix_open("/dev/android_adb_enable", O_RDWR);
+    if (fd < 0) {
+       D("failed to open /dev/android_adb_enable\n");
+    } else {
+        close_on_exec(fd);
+    }
+
+    D("[ usb_init - starting thread ]\n");
+    if(adb_thread_create(&tid, usb_adb_open_thread, h)){
+        fatal_errno("cannot create usb thread");
+    }
+}
+
+
+static void init_functionfs(struct usb_handle *h)
+{
+    ssize_t ret;
+
+    if (h->control < 0) { // might have already done this before
+        D("OPENING %s\n", USB_FFS_ADB_EP0);
+        h->control = adb_open(USB_FFS_ADB_EP0, O_RDWR);
+        if (h->control < 0) {
+            D("[ %s: cannot open control endpoint: errno=%d]\n", USB_FFS_ADB_EP0, errno);
+            goto err;
+        }
+
+        ret = adb_write(h->control, &descriptors, sizeof(descriptors));
+        if (ret < 0) {
+            D("[ %s: write descriptors failed: errno=%d ]\n", USB_FFS_ADB_EP0, errno);
+            goto err;
+        }
+
+        ret = adb_write(h->control, &strings, sizeof(strings));
+        if (ret < 0) {
+            D("[ %s: writing strings failed: errno=%d]\n", USB_FFS_ADB_EP0, errno);
+            goto err;
+        }
+    }
+
+    h->bulk_out = adb_open(USB_FFS_ADB_OUT, O_RDWR);
+    if (h->bulk_out < 0) {
+        D("[ %s: cannot open bulk-out ep: errno=%d ]\n", USB_FFS_ADB_OUT, errno);
+        goto err;
+    }
+
+    h->bulk_in = adb_open(USB_FFS_ADB_IN, O_RDWR);
+    if (h->bulk_in < 0) {
+        D("[ %s: cannot open bulk-in ep: errno=%d ]\n", USB_FFS_ADB_IN, errno);
+        goto err;
+    }
+
+    return;
+
+err:
+    if (h->bulk_in > 0) {
+        adb_close(h->bulk_in);
+        h->bulk_in = -1;
+    }
+    if (h->bulk_out > 0) {
+        adb_close(h->bulk_out);
+        h->bulk_out = -1;
+    }
+    if (h->control > 0) {
+        adb_close(h->control);
+        h->control = -1;
+    }
+    return;
+}
+
+static void *usb_ffs_open_thread(void *x)
+{
+    struct usb_handle *usb = (struct usb_handle *)x;
+
+    while (1) {
+        // wait until the USB device needs opening
+        adb_mutex_lock(&usb->lock);
+        while (usb->control != -1 && usb->bulk_in != -1 && usb->bulk_out != -1)
+            adb_cond_wait(&usb->notify, &usb->lock);
+        adb_mutex_unlock(&usb->lock);
+
+        while (1) {
+            init_functionfs(usb);
+
+            if (usb->control >= 0 && usb->bulk_in >= 0 && usb->bulk_out >= 0)
+                break;
+
+            adb_sleep_ms(1000);
+        }
+
+        D("[ usb_thread - registering device ]\n");
+        register_usb_transport(usb, 0, 0, 1);
+    }
+
+    // never gets here
+    return 0;
+}
+
+static int bulk_write(int bulk_in, const char *buf, size_t length)
+{
+    size_t count = 0;
+    int ret;
+
+    do {
+        ret = adb_write(bulk_in, buf + count, length - count);
+        if (ret < 0) {
+            if (errno != EINTR)
+                return ret;
+        } else {
+            count += ret;
+        }
+    } while (count < length);
+
+    D("[ bulk_write done fd=%d ]\n", bulk_in);
+    return count;
+}
+
+static int usb_ffs_write(usb_handle *h, const void *data, int len)
+{
+    int n;
+
+    D("about to write (fd=%d, len=%d)\n", h->bulk_in, len);
+    n = bulk_write(h->bulk_in, data, len);
+    if (n != len) {
+        D("ERROR: fd = %d, n = %d, errno = %d (%s)\n",
+            h->bulk_in, n, errno, strerror(errno));
+        return -1;
+    }
+    D("[ done fd=%d ]\n", h->bulk_in);
+    return 0;
+}
+
+static int bulk_read(int bulk_out, char *buf, size_t length)
+{
+    size_t count = 0;
+    int ret;
+
+    do {
+        ret = adb_read(bulk_out, buf + count, length - count);
+        if (ret < 0) {
+            if (errno != EINTR) {
+                D("[ bulk_read failed fd=%d length=%zu count=%zu ]\n",
+                                           bulk_out, length, count);
+                return ret;
+            }
+        } else {
+            count += ret;
+        }
+    } while (count < length);
+
+    return count;
+}
+
+static int usb_ffs_read(usb_handle *h, void *data, int len)
+{
+    int n;
+
+    D("about to read (fd=%d, len=%d)\n", h->bulk_out, len);
+    n = bulk_read(h->bulk_out, data, len);
+    if (n != len) {
+        D("ERROR: fd = %d, n = %d, errno = %d (%s)\n",
+            h->bulk_out, n, errno, strerror(errno));
+        return -1;
+    }
+    D("[ done fd=%d ]\n", h->bulk_out);
+    return 0;
+}
+
+static void usb_ffs_kick(usb_handle *h)
+{
+    int err;
+
+    err = ioctl(h->bulk_in, FUNCTIONFS_CLEAR_HALT);
+    if (err < 0)
+        D("[ kick: source (fd=%d) clear halt failed (%d) ]", h->bulk_in, errno);
+
+    err = ioctl(h->bulk_out, FUNCTIONFS_CLEAR_HALT);
+    if (err < 0)
+        D("[ kick: sink (fd=%d) clear halt failed (%d) ]", h->bulk_out, errno);
+
+    adb_mutex_lock(&h->lock);
+
+    // don't close ep0 here, since we may not need to reinitialize it with
+    // the same descriptors again. if however ep1/ep2 fail to re-open in
+    // init_functionfs, only then would we close and open ep0 again.
+    adb_close(h->bulk_out);
+    adb_close(h->bulk_in);
+    h->bulk_out = h->bulk_in = -1;
+
+    // notify usb_ffs_open_thread that we are disconnected
+    adb_cond_signal(&h->notify);
+    adb_mutex_unlock(&h->lock);
+}
+
+static void usb_ffs_init()
+{
+    usb_handle *h;
+    adb_thread_t tid;
+
+    D("[ usb_init - using FunctionFS ]\n");
+
+    h = calloc(1, sizeof(usb_handle));
+
+    h->write = usb_ffs_write;
+    h->read = usb_ffs_read;
+    h->kick = usb_ffs_kick;
+
+    h->control  = -1;
+    h->bulk_out = -1;
+    h->bulk_out = -1;
+
+    adb_cond_init(&h->notify, 0);
+    adb_mutex_init(&h->lock, 0);
+
+    D("[ usb_init - starting thread ]\n");
+    if (adb_thread_create(&tid, usb_ffs_open_thread, h)){
+        fatal_errno("[ cannot create usb thread ]\n");
+    }
+}
+
+void usb_init()
+{
+    if (access(USB_FFS_ADB_EP0, F_OK) == 0)
+        usb_ffs_init();
+    else
+        usb_adb_init();
+}
+
+void usb_cleanup()
+{
+}
+
+int usb_write(usb_handle *h, const void *data, int len)
+{
+    return h->write(h, data, len);
+}
+
+int usb_read(usb_handle *h, void *data, int len)
+{
+    return h->read(h, data, len);
+}
+int usb_close(usb_handle *h)
+{
+    return 0;
+}
+
+void usb_kick(usb_handle *h)
+{
+    h->kick(h);
+}
diff --git a/package/utils/adbd/src/adb/usb_osx.c b/package/utils/adbd/src/adb/usb_osx.c
new file mode 100644
index 0000000..45ce444
--- /dev/null
+++ b/package/utils/adbd/src/adb/usb_osx.c
@@ -0,0 +1,545 @@
+/*
+ * 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 <CoreFoundation/CoreFoundation.h>
+
+#include <IOKit/IOKitLib.h>
+#include <IOKit/IOCFPlugIn.h>
+#include <IOKit/usb/IOUSBLib.h>
+#include <IOKit/IOMessage.h>
+#include <mach/mach_port.h>
+
+#include "sysdeps.h"
+
+#include <stdio.h>
+
+#define TRACE_TAG   TRACE_USB
+#include "adb.h"
+#include "usb_vendors.h"
+
+#define  DBG   D
+
+static IONotificationPortRef    notificationPort = 0;
+static io_iterator_t*           notificationIterators;
+
+struct usb_handle
+{
+    UInt8                     bulkIn;
+    UInt8                     bulkOut;
+    IOUSBInterfaceInterface   **interface;
+    io_object_t               usbNotification;
+    unsigned int              zero_mask;
+};
+
+static CFRunLoopRef currentRunLoop = 0;
+static pthread_mutex_t start_lock;
+static pthread_cond_t start_cond;
+
+
+static void AndroidInterfaceAdded(void *refCon, io_iterator_t iterator);
+static void AndroidInterfaceNotify(void *refCon, io_iterator_t iterator,
+                                   natural_t messageType,
+                                   void *messageArgument);
+static usb_handle* CheckInterface(IOUSBInterfaceInterface **iface,
+                                  UInt16 vendor, UInt16 product);
+
+static int
+InitUSB()
+{
+    CFMutableDictionaryRef  matchingDict;
+    CFRunLoopSourceRef      runLoopSource;
+    SInt32                  vendor, if_subclass, if_protocol;
+    unsigned                i;
+
+    //* To set up asynchronous notifications, create a notification port and
+    //* add its run loop event source to the program's run loop
+    notificationPort = IONotificationPortCreate(kIOMasterPortDefault);
+    runLoopSource = IONotificationPortGetRunLoopSource(notificationPort);
+    CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopDefaultMode);
+
+    memset(notificationIterators, 0, sizeof(notificationIterators));
+
+    //* loop through all supported vendors
+    for (i = 0; i < vendorIdCount; i++) {
+        //* Create our matching dictionary to find the Android device's
+        //* adb interface
+        //* IOServiceAddMatchingNotification consumes the reference, so we do
+        //* not need to release this
+        matchingDict = IOServiceMatching(kIOUSBInterfaceClassName);
+
+        if (!matchingDict) {
+            DBG("ERR: Couldn't create USB matching dictionary.\n");
+            return -1;
+        }
+
+        //* Match based on vendor id, interface subclass and protocol
+        vendor = vendorIds[i];
+        if_subclass = ADB_SUBCLASS;
+        if_protocol = ADB_PROTOCOL;
+        CFDictionarySetValue(matchingDict, CFSTR(kUSBVendorID),
+                             CFNumberCreate(kCFAllocatorDefault,
+                                            kCFNumberSInt32Type, &vendor));
+        CFDictionarySetValue(matchingDict, CFSTR(kUSBInterfaceSubClass),
+                             CFNumberCreate(kCFAllocatorDefault,
+                                            kCFNumberSInt32Type, &if_subclass));
+        CFDictionarySetValue(matchingDict, CFSTR(kUSBInterfaceProtocol),
+                             CFNumberCreate(kCFAllocatorDefault,
+                                            kCFNumberSInt32Type, &if_protocol));
+        IOServiceAddMatchingNotification(
+                notificationPort,
+                kIOFirstMatchNotification,
+                matchingDict,
+                AndroidInterfaceAdded,
+                NULL,
+                &notificationIterators[i]);
+
+        //* Iterate over set of matching interfaces to access already-present
+        //* devices and to arm the notification
+        AndroidInterfaceAdded(NULL, notificationIterators[i]);
+    }
+
+    return 0;
+}
+
+static void
+AndroidInterfaceAdded(void *refCon, io_iterator_t iterator)
+{
+    kern_return_t            kr;
+    io_service_t             usbDevice;
+    io_service_t             usbInterface;
+    IOCFPlugInInterface      **plugInInterface = NULL;
+    IOUSBInterfaceInterface220  **iface = NULL;
+    IOUSBDeviceInterface197  **dev = NULL;
+    HRESULT                  result;
+    SInt32                   score;
+    UInt32                   locationId;
+    UInt16                   vendor;
+    UInt16                   product;
+    UInt8                    serialIndex;
+    char                     serial[256];
+    char                     devpathBuf[64];
+    char                     *devpath = NULL;
+
+    while ((usbInterface = IOIteratorNext(iterator))) {
+        //* Create an intermediate interface plugin
+        kr = IOCreatePlugInInterfaceForService(usbInterface,
+                                               kIOUSBInterfaceUserClientTypeID,
+                                               kIOCFPlugInInterfaceID,
+                                               &plugInInterface, &score);
+        IOObjectRelease(usbInterface);
+        if ((kIOReturnSuccess != kr) || (!plugInInterface)) {
+            DBG("ERR: Unable to create an interface plug-in (%08x)\n", kr);
+            continue;
+        }
+
+        //* This gets us the interface object
+        result = (*plugInInterface)->QueryInterface(plugInInterface,
+                CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID), (LPVOID)
+                &iface);
+        //* We only needed the plugin to get the interface, so discard it
+        (*plugInInterface)->Release(plugInInterface);
+        if (result || !iface) {
+            DBG("ERR: Couldn't query the interface (%08x)\n", (int) result);
+            continue;
+        }
+
+        //* this gets us an ioservice, with which we will find the actual
+        //* device; after getting a plugin, and querying the interface, of
+        //* course.
+        //* Gotta love OS X
+        kr = (*iface)->GetDevice(iface, &usbDevice);
+        if (kIOReturnSuccess != kr || !usbDevice) {
+            DBG("ERR: Couldn't grab device from interface (%08x)\n", kr);
+            continue;
+        }
+
+        plugInInterface = NULL;
+        score = 0;
+        //* create an intermediate device plugin
+        kr = IOCreatePlugInInterfaceForService(usbDevice,
+                                               kIOUSBDeviceUserClientTypeID,
+                                               kIOCFPlugInInterfaceID,
+                                               &plugInInterface, &score);
+        //* only needed this to find the plugin
+        (void)IOObjectRelease(usbDevice);
+        if ((kIOReturnSuccess != kr) || (!plugInInterface)) {
+            DBG("ERR: Unable to create a device plug-in (%08x)\n", kr);
+            continue;
+        }
+
+        result = (*plugInInterface)->QueryInterface(plugInInterface,
+                CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), (LPVOID) &dev);
+        //* only needed this to query the plugin
+        (*plugInInterface)->Release(plugInInterface);
+        if (result || !dev) {
+            DBG("ERR: Couldn't create a device interface (%08x)\n",
+                (int) result);
+            continue;
+        }
+
+        //* Now after all that, we actually have a ref to the device and
+        //* the interface that matched our criteria
+
+        kr = (*dev)->GetDeviceVendor(dev, &vendor);
+        kr = (*dev)->GetDeviceProduct(dev, &product);
+        kr = (*dev)->GetLocationID(dev, &locationId);
+        if (kr == 0) {
+            snprintf(devpathBuf, sizeof(devpathBuf), "usb:%lX", locationId);
+            devpath = devpathBuf;
+        }
+        kr = (*dev)->USBGetSerialNumberStringIndex(dev, &serialIndex);
+
+	if (serialIndex > 0) {
+		IOUSBDevRequest req;
+		UInt16          buffer[256];
+		UInt16          languages[128];
+
+		memset(languages, 0, sizeof(languages));
+
+		req.bmRequestType =
+			USBmakebmRequestType(kUSBIn, kUSBStandard, kUSBDevice);
+		req.bRequest = kUSBRqGetDescriptor;
+		req.wValue = (kUSBStringDesc << 8) | 0;
+		req.wIndex = 0;
+		req.pData = languages;
+		req.wLength = sizeof(languages);
+		kr = (*dev)->DeviceRequest(dev, &req);
+
+		if (kr == kIOReturnSuccess && req.wLenDone > 0) {
+
+			int langCount = (req.wLenDone - 2) / 2, lang;
+
+			for (lang = 1; lang <= langCount; lang++) {
+
+                                memset(buffer, 0, sizeof(buffer));
+                                memset(&req, 0, sizeof(req));
+
+				req.bmRequestType =
+					USBmakebmRequestType(kUSBIn, kUSBStandard, kUSBDevice);
+				req.bRequest = kUSBRqGetDescriptor;
+				req.wValue = (kUSBStringDesc << 8) | serialIndex;
+				req.wIndex = languages[lang];
+				req.pData = buffer;
+				req.wLength = sizeof(buffer);
+				kr = (*dev)->DeviceRequest(dev, &req);
+
+				if (kr == kIOReturnSuccess && req.wLenDone > 0) {
+					int i, count;
+
+					// skip first word, and copy the rest to the serial string,
+					// changing shorts to bytes.
+					count = (req.wLenDone - 1) / 2;
+					for (i = 0; i < count; i++)
+						serial[i] = buffer[i + 1];
+					serial[i] = 0;
+                                        break;
+				}
+			}
+		}
+	}
+        (*dev)->Release(dev);
+
+        DBG("INFO: Found vid=%04x pid=%04x serial=%s\n", vendor, product,
+            serial);
+
+        usb_handle* handle = CheckInterface((IOUSBInterfaceInterface**)iface,
+                                            vendor, product);
+        if (handle == NULL) {
+            DBG("ERR: Could not find device interface: %08x\n", kr);
+            (*iface)->Release(iface);
+            continue;
+        }
+
+        DBG("AndroidDeviceAdded calling register_usb_transport\n");
+        register_usb_transport(handle, (serial[0] ? serial : NULL), devpath, 1);
+
+        // Register for an interest notification of this device being removed.
+        // Pass the reference to our private data as the refCon for the
+        // notification.
+        kr = IOServiceAddInterestNotification(notificationPort,
+                usbInterface,
+                kIOGeneralInterest,
+                AndroidInterfaceNotify,
+                handle,
+                &handle->usbNotification);
+
+        if (kIOReturnSuccess != kr) {
+            DBG("ERR: Unable to create interest notification (%08x)\n", kr);
+        }
+    }
+}
+
+static void
+AndroidInterfaceNotify(void *refCon, io_service_t service, natural_t messageType, void *messageArgument)
+{
+    usb_handle *handle = (usb_handle *)refCon;
+
+    if (messageType == kIOMessageServiceIsTerminated) {
+        if (!handle) {
+            DBG("ERR: NULL handle\n");
+            return;
+        }
+        DBG("AndroidInterfaceNotify\n");
+        IOObjectRelease(handle->usbNotification);
+        usb_kick(handle);
+    }
+}
+
+//* TODO: simplify this further since we only register to get ADB interface
+//* subclass+protocol events
+static usb_handle*
+CheckInterface(IOUSBInterfaceInterface **interface, UInt16 vendor, UInt16 product)
+{
+    usb_handle*                 handle = NULL;
+    IOReturn                    kr;
+    UInt8  interfaceNumEndpoints, interfaceClass, interfaceSubClass, interfaceProtocol;
+    UInt8  endpoint;
+
+
+    //* Now open the interface.  This will cause the pipes associated with
+    //* the endpoints in the interface descriptor to be instantiated
+    kr = (*interface)->USBInterfaceOpen(interface);
+    if (kr != kIOReturnSuccess) {
+        DBG("ERR: Could not open interface: (%08x)\n", kr);
+        return NULL;
+    }
+
+    //* Get the number of endpoints associated with this interface
+    kr = (*interface)->GetNumEndpoints(interface, &interfaceNumEndpoints);
+    if (kr != kIOReturnSuccess) {
+        DBG("ERR: Unable to get number of endpoints: (%08x)\n", kr);
+        goto err_get_num_ep;
+    }
+
+    //* Get interface class, subclass and protocol
+    if ((*interface)->GetInterfaceClass(interface, &interfaceClass) != kIOReturnSuccess ||
+            (*interface)->GetInterfaceSubClass(interface, &interfaceSubClass) != kIOReturnSuccess ||
+            (*interface)->GetInterfaceProtocol(interface, &interfaceProtocol) != kIOReturnSuccess) {
+            DBG("ERR: Unable to get interface class, subclass and protocol\n");
+            goto err_get_interface_class;
+    }
+
+    //* check to make sure interface class, subclass and protocol match ADB
+    //* avoid opening mass storage endpoints
+    if (!is_adb_interface(vendor, product, interfaceClass,
+                interfaceSubClass, interfaceProtocol))
+        goto err_bad_adb_interface;
+
+    handle = calloc(1, sizeof(usb_handle));
+
+    //* Iterate over the endpoints for this interface and find the first
+    //* bulk in/out pipes available.  These will be our read/write pipes.
+    for (endpoint = 0; endpoint <= interfaceNumEndpoints; endpoint++) {
+        UInt8   transferType;
+        UInt16  maxPacketSize;
+        UInt8   interval;
+        UInt8   number;
+        UInt8   direction;
+
+        kr = (*interface)->GetPipeProperties(interface, endpoint, &direction,
+                &number, &transferType, &maxPacketSize, &interval);
+
+        if (kIOReturnSuccess == kr) {
+            if (kUSBBulk != transferType)
+                continue;
+
+            if (kUSBIn == direction)
+                handle->bulkIn = endpoint;
+
+            if (kUSBOut == direction)
+                handle->bulkOut = endpoint;
+
+            handle->zero_mask = maxPacketSize - 1;
+        } else {
+            DBG("ERR: FindDeviceInterface - could not get pipe properties\n");
+            goto err_get_pipe_props;
+        }
+    }
+
+    handle->interface = interface;
+    return handle;
+
+err_get_pipe_props:
+    free(handle);
+err_bad_adb_interface:
+err_get_interface_class:
+err_get_num_ep:
+    (*interface)->USBInterfaceClose(interface);
+    return NULL;
+}
+
+
+void* RunLoopThread(void* unused)
+{
+    unsigned i;
+
+    InitUSB();
+
+    currentRunLoop = CFRunLoopGetCurrent();
+
+    // Signal the parent that we are running
+    adb_mutex_lock(&start_lock);
+    adb_cond_signal(&start_cond);
+    adb_mutex_unlock(&start_lock);
+
+    CFRunLoopRun();
+    currentRunLoop = 0;
+
+    for (i = 0; i < vendorIdCount; i++) {
+        IOObjectRelease(notificationIterators[i]);
+    }
+    IONotificationPortDestroy(notificationPort);
+
+    DBG("RunLoopThread done\n");
+    return NULL;    
+}
+
+
+static int initialized = 0;
+void usb_init()
+{
+    if (!initialized)
+    {
+        adb_thread_t    tid;
+
+        notificationIterators = (io_iterator_t*)malloc(
+            vendorIdCount * sizeof(io_iterator_t));
+
+        adb_mutex_init(&start_lock, NULL);
+        adb_cond_init(&start_cond, NULL);
+
+        if(adb_thread_create(&tid, RunLoopThread, NULL))
+            fatal_errno("cannot create input thread");
+
+        // Wait for initialization to finish
+        adb_mutex_lock(&start_lock);
+        adb_cond_wait(&start_cond, &start_lock);
+        adb_mutex_unlock(&start_lock);
+
+        adb_mutex_destroy(&start_lock);
+        adb_cond_destroy(&start_cond);
+
+        initialized = 1;
+    }
+}
+
+void usb_cleanup()
+{
+    DBG("usb_cleanup\n");
+    close_usb_devices();
+    if (currentRunLoop)
+        CFRunLoopStop(currentRunLoop);
+
+    if (notificationIterators != NULL) {
+        free(notificationIterators);
+        notificationIterators = NULL;
+    }
+}
+
+int usb_write(usb_handle *handle, const void *buf, int len)
+{
+    IOReturn    result;
+
+    if (!len)
+        return 0;
+
+    if (!handle)
+        return -1;
+
+    if (NULL == handle->interface) {
+        DBG("ERR: usb_write interface was null\n");
+        return -1;
+    }
+
+    if (0 == handle->bulkOut) {
+        DBG("ERR: bulkOut endpoint not assigned\n");
+        return -1;
+    }
+
+    result =
+        (*handle->interface)->WritePipe(
+                              handle->interface, handle->bulkOut, (void *)buf, len);
+
+    if ((result == 0) && (handle->zero_mask)) {
+        /* we need 0-markers and our transfer */
+        if(!(len & handle->zero_mask)) {
+            result =
+                (*handle->interface)->WritePipe(
+                        handle->interface, handle->bulkOut, (void *)buf, 0);
+        }
+    }
+
+    if (0 == result)
+        return 0;
+
+    DBG("ERR: usb_write failed with status %d\n", result);
+    return -1;
+}
+
+int usb_read(usb_handle *handle, void *buf, int len)
+{
+    IOReturn result;
+    UInt32  numBytes = len;
+
+    if (!len) {
+        return 0;
+    }
+
+    if (!handle) {
+        return -1;
+    }
+
+    if (NULL == handle->interface) {
+        DBG("ERR: usb_read interface was null\n");
+        return -1;
+    }
+
+    if (0 == handle->bulkIn) {
+        DBG("ERR: bulkIn endpoint not assigned\n");
+        return -1;
+    }
+
+    result =
+      (*handle->interface)->ReadPipe(handle->interface,
+                                    handle->bulkIn, buf, &numBytes);
+
+    if (0 == result)
+        return 0;
+    else {
+        DBG("ERR: usb_read failed with status %d\n", result);
+    }
+
+    return -1;
+}
+
+int usb_close(usb_handle *handle)
+{
+    return 0;
+}
+
+void usb_kick(usb_handle *handle)
+{
+    /* release the interface */
+    if (!handle)
+        return;
+
+    if (handle->interface)
+    {
+        (*handle->interface)->USBInterfaceClose(handle->interface);
+        (*handle->interface)->Release(handle->interface);
+        handle->interface = 0;
+    }
+}
diff --git a/package/utils/adbd/src/adb/usb_vendors.c b/package/utils/adbd/src/adb/usb_vendors.c
new file mode 100644
index 0000000..957e5db
--- /dev/null
+++ b/package/utils/adbd/src/adb/usb_vendors.c
@@ -0,0 +1,367 @@
+/*
+ * Copyright (C) 2009 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 "usb_vendors.h"
+
+#include <stdio.h>
+
+#ifdef _WIN32
+#  define WIN32_LEAN_AND_MEAN
+#  include "windows.h"
+#  include "shlobj.h"
+#else
+#  include <unistd.h>
+#  include <sys/stat.h>
+#endif
+
+#include "sysdeps.h"
+#include "adb.h"
+
+#define ANDROID_PATH            ".android"
+#define ANDROID_ADB_INI         "adb_usb.ini"
+
+#define TRACE_TAG               TRACE_USB
+
+/* Keep the list below sorted alphabetically by #define name */
+// Acer's USB Vendor ID
+#define VENDOR_ID_ACER          0x0502
+// Allwinner's USB Vendor ID
+#define VENDOR_ID_ALLWINNER     0x1F3A
+// Amlogic's USB Vendor ID
+#define VENDOR_ID_AMLOGIC       0x1b8e
+// AnyDATA's USB Vendor ID
+#define VENDOR_ID_ANYDATA       0x16D5
+// Archos's USB Vendor ID
+#define VENDOR_ID_ARCHOS        0x0E79
+// Asus's USB Vendor ID
+#define VENDOR_ID_ASUS          0x0b05
+// BYD's USB Vendor ID
+#define VENDOR_ID_BYD           0x1D91
+// Compal's USB Vendor ID
+#define VENDOR_ID_COMPAL        0x04B7
+// Compalcomm's USB Vendor ID
+#define VENDOR_ID_COMPALCOMM    0x1219
+// Dell's USB Vendor ID
+#define VENDOR_ID_DELL          0x413c
+// ECS's USB Vendor ID
+#define VENDOR_ID_ECS           0x03fc
+// EMERGING_TECH's USB Vendor ID
+#define VENDOR_ID_EMERGING_TECH 0x297F
+// Emerson's USB Vendor ID
+#define VENDOR_ID_EMERSON       0x2207
+// Foxconn's USB Vendor ID
+#define VENDOR_ID_FOXCONN       0x0489
+// Fujitsu's USB Vendor ID
+#define VENDOR_ID_FUJITSU       0x04C5
+// Funai's USB Vendor ID
+#define VENDOR_ID_FUNAI         0x0F1C
+// Garmin-Asus's USB Vendor ID
+#define VENDOR_ID_GARMIN_ASUS   0x091E
+// Gigabyte's USB Vendor ID
+#define VENDOR_ID_GIGABYTE      0x0414
+// Gigaset's USB Vendor ID
+#define VENDOR_ID_GIGASET       0x1E85
+// GIONEE's USB Vendor ID
+#define VENDOR_ID_GIONEE        0x271D
+// Google's USB Vendor ID
+#define VENDOR_ID_GOOGLE        0x18d1
+// Haier's USB Vendor ID
+#define VENDOR_ID_HAIER         0x201E
+// Harris's USB Vendor ID
+#define VENDOR_ID_HARRIS        0x19A5
+// Hisense's USB Vendor ID
+#define VENDOR_ID_HISENSE       0x109b
+// Honeywell's USB Vendor ID
+#define VENDOR_ID_HONEYWELL     0x0c2e
+// HP's USB Vendor ID
+#define VENDOR_ID_HP            0x03f0
+// HTC's USB Vendor ID
+#define VENDOR_ID_HTC           0x0bb4
+// Huawei's USB Vendor ID
+#define VENDOR_ID_HUAWEI        0x12D1
+// INQ Mobile's USB Vendor ID
+#define VENDOR_ID_INQ_MOBILE    0x2314
+// Intel's USB Vendor ID
+#define VENDOR_ID_INTEL         0x8087
+// Intermec's USB Vendor ID
+#define VENDOR_ID_INTERMEC      0x067e
+// IRiver's USB Vendor ID
+#define VENDOR_ID_IRIVER        0x2420
+// K-Touch's USB Vendor ID
+#define VENDOR_ID_K_TOUCH       0x24E3
+// KT Tech's USB Vendor ID
+#define VENDOR_ID_KT_TECH       0x2116
+// Kobo's USB Vendor ID
+#define VENDOR_ID_KOBO          0x2237
+// Kyocera's USB Vendor ID
+#define VENDOR_ID_KYOCERA       0x0482
+// Lab126's USB Vendor ID
+#define VENDOR_ID_LAB126        0x1949
+// Lenovo's USB Vendor ID
+#define VENDOR_ID_LENOVO        0x17EF
+// LenovoMobile's USB Vendor ID
+#define VENDOR_ID_LENOVOMOBILE  0x2006
+// LG's USB Vendor ID
+#define VENDOR_ID_LGE           0x1004
+// Lumigon's USB Vendor ID
+#define VENDOR_ID_LUMIGON       0x25E3
+// Motorola's USB Vendor ID
+#define VENDOR_ID_MOTOROLA      0x22b8
+// MSI's USB Vendor ID
+#define VENDOR_ID_MSI           0x0DB0
+// MTK's USB Vendor ID
+#define VENDOR_ID_MTK           0x0e8d
+// NEC's USB Vendor ID
+#define VENDOR_ID_NEC           0x0409
+// B&N Nook's USB Vendor ID
+#define VENDOR_ID_NOOK          0x2080
+// Nvidia's USB Vendor ID
+#define VENDOR_ID_NVIDIA        0x0955
+// OPPO's USB Vendor ID
+#define VENDOR_ID_OPPO          0x22D9
+// On-The-Go-Video's USB Vendor ID
+#define VENDOR_ID_OTGV          0x2257
+// OUYA's USB Vendor ID
+#define VENDOR_ID_OUYA          0x2836
+// Pantech's USB Vendor ID
+#define VENDOR_ID_PANTECH       0x10A9
+// Pegatron's USB Vendor ID
+#define VENDOR_ID_PEGATRON      0x1D4D
+// Philips's USB Vendor ID
+#define VENDOR_ID_PHILIPS       0x0471
+// Panasonic Mobile Communication's USB Vendor ID
+#define VENDOR_ID_PMC           0x04DA
+// Positivo's USB Vendor ID
+#define VENDOR_ID_POSITIVO      0x1662
+// Prestigio's USB Vendor ID
+#define VENDOR_ID_PRESTIGIO     0x29e4
+// Qisda's USB Vendor ID
+#define VENDOR_ID_QISDA         0x1D45
+// Qualcomm's USB Vendor ID
+#define VENDOR_ID_QUALCOMM      0x05c6
+// Quanta's USB Vendor ID
+#define VENDOR_ID_QUANTA        0x0408
+// Rockchip's USB Vendor ID
+#define VENDOR_ID_ROCKCHIP      0x2207
+// Samsung's USB Vendor ID
+#define VENDOR_ID_SAMSUNG       0x04e8
+// Sharp's USB Vendor ID
+#define VENDOR_ID_SHARP         0x04dd
+// SK Telesys's USB Vendor ID
+#define VENDOR_ID_SK_TELESYS    0x1F53
+// Smartisan's USB Vendor ID
+#define VENDOR_ID_SMARTISAN     0x29a9
+// Sony's USB Vendor ID
+#define VENDOR_ID_SONY          0x054C
+// Sony Ericsson's USB Vendor ID
+#define VENDOR_ID_SONY_ERICSSON 0x0FCE
+// T & A Mobile Phones' USB Vendor ID
+#define VENDOR_ID_T_AND_A       0x1BBB
+// TechFaith's USB Vendor ID
+#define VENDOR_ID_TECHFAITH     0x1d09
+// Teleepoch's USB Vendor ID
+#define VENDOR_ID_TELEEPOCH     0x2340
+// Texas Instruments's USB Vendor ID
+#define VENDOR_ID_TI            0x0451
+// Toshiba's USB Vendor ID
+#define VENDOR_ID_TOSHIBA       0x0930
+// Unowhy's USB Vendor ID
+#define VENDOR_ID_UNOWHY        0x2A49
+// Vizio's USB Vendor ID
+#define VENDOR_ID_VIZIO         0xE040
+// Wacom's USB Vendor ID
+#define VENDOR_ID_WACOM         0x0531
+// Xiaomi's USB Vendor ID
+#define VENDOR_ID_XIAOMI        0x2717
+// YotaDevices's USB Vendor ID
+#define VENDOR_ID_YOTADEVICES   0x2916
+// Yulong Coolpad's USB Vendor ID
+#define VENDOR_ID_YULONG_COOLPAD 0x1EBF
+// ZTE's USB Vendor ID
+#define VENDOR_ID_ZTE           0x19D2
+/* Keep the list above sorted alphabetically by #define name */
+
+/** built-in vendor list */
+/* Keep the list below sorted alphabetically */
+int builtInVendorIds[] = {
+    VENDOR_ID_ACER,
+    VENDOR_ID_ALLWINNER,
+    VENDOR_ID_AMLOGIC,
+    VENDOR_ID_ANYDATA,
+    VENDOR_ID_ARCHOS,
+    VENDOR_ID_ASUS,
+    VENDOR_ID_BYD,
+    VENDOR_ID_COMPAL,
+    VENDOR_ID_COMPALCOMM,
+    VENDOR_ID_DELL,
+    VENDOR_ID_ECS,
+    VENDOR_ID_EMERGING_TECH,
+    VENDOR_ID_EMERSON,
+    VENDOR_ID_FOXCONN,
+    VENDOR_ID_FUJITSU,
+    VENDOR_ID_FUNAI,
+    VENDOR_ID_GARMIN_ASUS,
+    VENDOR_ID_GIGABYTE,
+    VENDOR_ID_GIGASET,
+    VENDOR_ID_GIONEE,
+    VENDOR_ID_GOOGLE,
+    VENDOR_ID_HAIER,
+    VENDOR_ID_HARRIS,
+    VENDOR_ID_HISENSE,
+    VENDOR_ID_HONEYWELL,
+    VENDOR_ID_HP,
+    VENDOR_ID_HTC,
+    VENDOR_ID_HUAWEI,
+    VENDOR_ID_INQ_MOBILE,
+    VENDOR_ID_INTEL,
+    VENDOR_ID_INTERMEC,
+    VENDOR_ID_IRIVER,
+    VENDOR_ID_KOBO,
+    VENDOR_ID_K_TOUCH,
+    VENDOR_ID_KT_TECH,
+    VENDOR_ID_KYOCERA,
+    VENDOR_ID_LAB126,
+    VENDOR_ID_LENOVO,
+    VENDOR_ID_LENOVOMOBILE,
+    VENDOR_ID_LGE,
+    VENDOR_ID_LUMIGON,
+    VENDOR_ID_MOTOROLA,
+    VENDOR_ID_MSI,
+    VENDOR_ID_MTK,
+    VENDOR_ID_NEC,
+    VENDOR_ID_NOOK,
+    VENDOR_ID_NVIDIA,
+    VENDOR_ID_OPPO,
+    VENDOR_ID_OTGV,
+    VENDOR_ID_OUYA,
+    VENDOR_ID_PANTECH,
+    VENDOR_ID_PEGATRON,
+    VENDOR_ID_PHILIPS,
+    VENDOR_ID_PMC,
+    VENDOR_ID_POSITIVO,
+    VENDOR_ID_PRESTIGIO,
+    VENDOR_ID_QISDA,
+    VENDOR_ID_QUALCOMM,
+    VENDOR_ID_QUANTA,
+    VENDOR_ID_ROCKCHIP,
+    VENDOR_ID_SAMSUNG,
+    VENDOR_ID_SHARP,
+    VENDOR_ID_SK_TELESYS,
+    VENDOR_ID_SMARTISAN,
+    VENDOR_ID_SONY,
+    VENDOR_ID_SONY_ERICSSON,
+    VENDOR_ID_T_AND_A,
+    VENDOR_ID_TECHFAITH,
+    VENDOR_ID_TELEEPOCH,
+    VENDOR_ID_TI,
+    VENDOR_ID_TOSHIBA,
+    VENDOR_ID_UNOWHY,
+    VENDOR_ID_VIZIO,
+    VENDOR_ID_WACOM,
+    VENDOR_ID_XIAOMI,
+    VENDOR_ID_YOTADEVICES,
+    VENDOR_ID_YULONG_COOLPAD,
+    VENDOR_ID_ZTE,
+};
+/* Keep the list above sorted alphabetically */
+
+#define BUILT_IN_VENDOR_COUNT    (sizeof(builtInVendorIds)/sizeof(builtInVendorIds[0]))
+
+/* max number of supported vendor ids (built-in + 3rd party). increase as needed */
+#define VENDOR_COUNT_MAX         128
+
+int vendorIds[VENDOR_COUNT_MAX];
+unsigned vendorIdCount = 0;
+
+int get_adb_usb_ini(char* buff, size_t len);
+
+void usb_vendors_init(void)
+{
+    if (VENDOR_COUNT_MAX < BUILT_IN_VENDOR_COUNT) {
+        fprintf(stderr, "VENDOR_COUNT_MAX not big enough for built-in vendor list.\n");
+        exit(2);
+    }
+
+    /* add the built-in vendors at the beginning of the array */
+    memcpy(vendorIds, builtInVendorIds, sizeof(builtInVendorIds));
+
+    /* default array size is the number of built-in vendors */
+    vendorIdCount = BUILT_IN_VENDOR_COUNT;
+
+    if (VENDOR_COUNT_MAX == BUILT_IN_VENDOR_COUNT)
+        return;
+
+    char temp[PATH_MAX];
+    if (get_adb_usb_ini(temp, sizeof(temp)) == 0) {
+        FILE * f = fopen(temp, "rt");
+
+        if (f != NULL) {
+            /* The vendor id file is pretty basic. 1 vendor id per line.
+               Lines starting with # are comments */
+            while (fgets(temp, sizeof(temp), f) != NULL) {
+                if (temp[0] == '#')
+                    continue;
+
+                long value = strtol(temp, NULL, 0);
+                if (errno == EINVAL || errno == ERANGE || value > INT_MAX || value < 0) {
+                    fprintf(stderr, "Invalid content in %s. Quitting.\n", ANDROID_ADB_INI);
+                    exit(2);
+                }
+
+                vendorIds[vendorIdCount++] = (int)value;
+
+                /* make sure we don't go beyond the array */
+                if (vendorIdCount == VENDOR_COUNT_MAX) {
+                    break;
+                }
+            }
+            fclose(f);
+        }
+    }
+}
+
+/* Utils methods */
+
+/* builds the path to the adb vendor id file. returns 0 if success */
+int build_path(char* buff, size_t len, const char* format, const char* home)
+{
+    if (snprintf(buff, len, format, home, ANDROID_PATH, ANDROID_ADB_INI) >= (signed)len) {
+        return 1;
+    }
+
+    return 0;
+}
+
+/* fills buff with the path to the adb vendor id file. returns 0 if success */
+int get_adb_usb_ini(char* buff, size_t len)
+{
+#ifdef _WIN32
+    const char* home = getenv("ANDROID_SDK_HOME");
+    if (home != NULL) {
+        return build_path(buff, len, "%s\\%s\\%s", home);
+    } else {
+        char path[MAX_PATH];
+        SHGetFolderPath( NULL, CSIDL_PROFILE, NULL, 0, path);
+        return build_path(buff, len, "%s\\%s\\%s", path);
+    }
+#else
+    const char* home = getenv("HOME");
+    if (home == NULL)
+        home = "/tmp";
+
+    return build_path(buff, len, "%s/%s/%s", home);
+#endif
+}
diff --git a/package/utils/adbd/src/adb/usb_vendors.h b/package/utils/adbd/src/adb/usb_vendors.h
new file mode 100644
index 0000000..cee23a1
--- /dev/null
+++ b/package/utils/adbd/src/adb/usb_vendors.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2009 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 __USB_VENDORS_H
+#define __USB_VENDORS_H
+
+extern int vendorIds[];
+extern unsigned  vendorIdCount;
+
+void usb_vendors_init(void);
+
+#endif
diff --git a/package/utils/adbd/src/adb/usb_windows.c b/package/utils/adbd/src/adb/usb_windows.c
new file mode 100644
index 0000000..1309a78
--- /dev/null
+++ b/package/utils/adbd/src/adb/usb_windows.c
@@ -0,0 +1,515 @@
+/*
+ * 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 <windows.h>
+#include <winerror.h>
+#include <errno.h>
+#include <usb100.h>
+#include <adb_api.h>
+#include <stdio.h>
+
+#include "sysdeps.h"
+
+#define   TRACE_TAG  TRACE_USB
+#include "adb.h"
+
+/** Structure usb_handle describes our connection to the usb device via
+  AdbWinApi.dll. This structure is returned from usb_open() routine and
+  is expected in each subsequent call that is accessing the device.
+*/
+struct usb_handle {
+  /// Previous entry in the list of opened usb handles
+  usb_handle *prev;
+
+  /// Next entry in the list of opened usb handles
+  usb_handle *next;
+
+  /// Handle to USB interface
+  ADBAPIHANDLE  adb_interface;
+
+  /// Handle to USB read pipe (endpoint)
+  ADBAPIHANDLE  adb_read_pipe;
+
+  /// Handle to USB write pipe (endpoint)
+  ADBAPIHANDLE  adb_write_pipe;
+
+  /// Interface name
+  char*         interface_name;
+
+  /// Mask for determining when to use zero length packets
+  unsigned zero_mask;
+};
+
+/// Class ID assigned to the device by androidusb.sys
+static const GUID usb_class_id = ANDROID_USB_CLASS_ID;
+
+/// List of opened usb handles
+static usb_handle handle_list = {
+  .prev = &handle_list,
+  .next = &handle_list,
+};
+
+/// Locker for the list of opened usb handles
+ADB_MUTEX_DEFINE( usb_lock );
+
+/// Checks if there is opened usb handle in handle_list for this device.
+int known_device(const char* dev_name);
+
+/// Checks if there is opened usb handle in handle_list for this device.
+/// usb_lock mutex must be held before calling this routine.
+int known_device_locked(const char* dev_name);
+
+/// Registers opened usb handle (adds it to handle_list).
+int register_new_device(usb_handle* handle);
+
+/// Checks if interface (device) matches certain criteria
+int recognized_device(usb_handle* handle);
+
+/// Enumerates present and available interfaces (devices), opens new ones and
+/// registers usb transport for them.
+void find_devices();
+
+/// Entry point for thread that polls (every second) for new usb interfaces.
+/// This routine calls find_devices in infinite loop.
+void* device_poll_thread(void* unused);
+
+/// Initializes this module
+void usb_init();
+
+/// Cleans up this module
+void usb_cleanup();
+
+/// Opens usb interface (device) by interface (device) name.
+usb_handle* do_usb_open(const wchar_t* interface_name);
+
+/// Writes data to the opened usb handle
+int usb_write(usb_handle* handle, const void* data, int len);
+
+/// Reads data using the opened usb handle
+int usb_read(usb_handle *handle, void* data, int len);
+
+/// Cleans up opened usb handle
+void usb_cleanup_handle(usb_handle* handle);
+
+/// Cleans up (but don't close) opened usb handle
+void usb_kick(usb_handle* handle);
+
+/// Closes opened usb handle
+int usb_close(usb_handle* handle);
+
+/// Gets interface (device) name for an opened usb handle
+const char *usb_name(usb_handle* handle);
+
+int known_device_locked(const char* dev_name) {
+  usb_handle* usb;
+
+  if (NULL != dev_name) {
+    // Iterate through the list looking for the name match.
+    for(usb = handle_list.next; usb != &handle_list; usb = usb->next) {
+      // In Windows names are not case sensetive!
+      if((NULL != usb->interface_name) &&
+         (0 == stricmp(usb->interface_name, dev_name))) {
+        return 1;
+      }
+    }
+  }
+
+  return 0;
+}
+
+int known_device(const char* dev_name) {
+  int ret = 0;
+
+  if (NULL != dev_name) {
+    adb_mutex_lock(&usb_lock);
+    ret = known_device_locked(dev_name);
+    adb_mutex_unlock(&usb_lock);
+  }
+
+  return ret;
+}
+
+int register_new_device(usb_handle* handle) {
+  if (NULL == handle)
+    return 0;
+
+  adb_mutex_lock(&usb_lock);
+
+  // Check if device is already in the list
+  if (known_device_locked(handle->interface_name)) {
+    adb_mutex_unlock(&usb_lock);
+    return 0;
+  }
+
+  // Not in the list. Add this handle to the list.
+  handle->next = &handle_list;
+  handle->prev = handle_list.prev;
+  handle->prev->next = handle;
+  handle->next->prev = handle;
+
+  adb_mutex_unlock(&usb_lock);
+
+  return 1;
+}
+
+void* device_poll_thread(void* unused) {
+  D("Created device thread\n");
+
+  while(1) {
+    find_devices();
+    adb_sleep_ms(1000);
+  }
+
+  return NULL;
+}
+
+void usb_init() {
+  adb_thread_t tid;
+
+  if(adb_thread_create(&tid, device_poll_thread, NULL)) {
+    fatal_errno("cannot create input thread");
+  }
+}
+
+void usb_cleanup() {
+}
+
+usb_handle* do_usb_open(const wchar_t* interface_name) {
+  // Allocate our handle
+  usb_handle* ret = (usb_handle*)malloc(sizeof(usb_handle));
+  if (NULL == ret)
+    return NULL;
+
+  // Set linkers back to the handle
+  ret->next = ret;
+  ret->prev = ret;
+
+  // Create interface.
+  ret->adb_interface = AdbCreateInterfaceByName(interface_name);
+
+  if (NULL == ret->adb_interface) {
+    free(ret);
+    errno = GetLastError();
+    return NULL;
+  }
+
+  // Open read pipe (endpoint)
+  ret->adb_read_pipe =
+    AdbOpenDefaultBulkReadEndpoint(ret->adb_interface,
+                                   AdbOpenAccessTypeReadWrite,
+                                   AdbOpenSharingModeReadWrite);
+  if (NULL != ret->adb_read_pipe) {
+    // Open write pipe (endpoint)
+    ret->adb_write_pipe =
+      AdbOpenDefaultBulkWriteEndpoint(ret->adb_interface,
+                                      AdbOpenAccessTypeReadWrite,
+                                      AdbOpenSharingModeReadWrite);
+    if (NULL != ret->adb_write_pipe) {
+      // Save interface name
+      unsigned long name_len = 0;
+
+      // First get expected name length
+      AdbGetInterfaceName(ret->adb_interface,
+                          NULL,
+                          &name_len,
+                          true);
+      if (0 != name_len) {
+        ret->interface_name = (char*)malloc(name_len);
+
+        if (NULL != ret->interface_name) {
+          // Now save the name
+          if (AdbGetInterfaceName(ret->adb_interface,
+                                  ret->interface_name,
+                                  &name_len,
+                                  true)) {
+            // We're done at this point
+            return ret;
+          }
+        } else {
+          SetLastError(ERROR_OUTOFMEMORY);
+        }
+      }
+    }
+  }
+
+  // Something went wrong.
+  int saved_errno = GetLastError();
+  usb_cleanup_handle(ret);
+  free(ret);
+  SetLastError(saved_errno);
+
+  return NULL;
+}
+
+int usb_write(usb_handle* handle, const void* data, int len) {
+  unsigned long time_out = 5000;
+  unsigned long written = 0;
+  int ret;
+
+  D("usb_write %d\n", len);
+  if (NULL != handle) {
+    // Perform write
+    ret = AdbWriteEndpointSync(handle->adb_write_pipe,
+                               (void*)data,
+                               (unsigned long)len,
+                               &written,
+                               time_out);
+    int saved_errno = GetLastError();
+
+    if (ret) {
+      // Make sure that we've written what we were asked to write
+      D("usb_write got: %ld, expected: %d\n", written, len);
+      if (written == (unsigned long)len) {
+        if(handle->zero_mask && (len & handle->zero_mask) == 0) {
+          // Send a zero length packet
+          AdbWriteEndpointSync(handle->adb_write_pipe,
+                               (void*)data,
+                               0,
+                               &written,
+                               time_out);
+        }
+        return 0;
+      }
+    } else {
+      // assume ERROR_INVALID_HANDLE indicates we are disconnected
+      if (saved_errno == ERROR_INVALID_HANDLE)
+        usb_kick(handle);
+    }
+    errno = saved_errno;
+  } else {
+    D("usb_write NULL handle\n");
+    SetLastError(ERROR_INVALID_HANDLE);
+  }
+
+  D("usb_write failed: %d\n", errno);
+
+  return -1;
+}
+
+int usb_read(usb_handle *handle, void* data, int len) {
+  unsigned long time_out = 0;
+  unsigned long read = 0;
+  int ret;
+
+  D("usb_read %d\n", len);
+  if (NULL != handle) {
+    while (len > 0) {
+      int xfer = (len > 4096) ? 4096 : len;
+
+      ret = AdbReadEndpointSync(handle->adb_read_pipe,
+                                  data,
+                                  (unsigned long)xfer,
+                                  &read,
+                                  time_out);
+      int saved_errno = GetLastError();
+      D("usb_write got: %ld, expected: %d, errno: %d\n", read, xfer, saved_errno);
+      if (ret) {
+        data = (char *)data + read;
+        len -= read;
+
+        if (len == 0)
+          return 0;
+      } else {
+        // assume ERROR_INVALID_HANDLE indicates we are disconnected
+        if (saved_errno == ERROR_INVALID_HANDLE)
+          usb_kick(handle);
+        break;
+      }
+      errno = saved_errno;
+    }
+  } else {
+    D("usb_read NULL handle\n");
+    SetLastError(ERROR_INVALID_HANDLE);
+  }
+
+  D("usb_read failed: %d\n", errno);
+
+  return -1;
+}
+
+void usb_cleanup_handle(usb_handle* handle) {
+  if (NULL != handle) {
+    if (NULL != handle->interface_name)
+      free(handle->interface_name);
+    if (NULL != handle->adb_write_pipe)
+      AdbCloseHandle(handle->adb_write_pipe);
+    if (NULL != handle->adb_read_pipe)
+      AdbCloseHandle(handle->adb_read_pipe);
+    if (NULL != handle->adb_interface)
+      AdbCloseHandle(handle->adb_interface);
+
+    handle->interface_name = NULL;
+    handle->adb_write_pipe = NULL;
+    handle->adb_read_pipe = NULL;
+    handle->adb_interface = NULL;
+  }
+}
+
+void usb_kick(usb_handle* handle) {
+  if (NULL != handle) {
+    adb_mutex_lock(&usb_lock);
+
+    usb_cleanup_handle(handle);
+
+    adb_mutex_unlock(&usb_lock);
+  } else {
+    SetLastError(ERROR_INVALID_HANDLE);
+    errno = ERROR_INVALID_HANDLE;
+  }
+}
+
+int usb_close(usb_handle* handle) {
+  D("usb_close\n");
+
+  if (NULL != handle) {
+    // Remove handle from the list
+    adb_mutex_lock(&usb_lock);
+
+    if ((handle->next != handle) && (handle->prev != handle)) {
+      handle->next->prev = handle->prev;
+      handle->prev->next = handle->next;
+      handle->prev = handle;
+      handle->next = handle;
+    }
+
+    adb_mutex_unlock(&usb_lock);
+
+    // Cleanup handle
+    usb_cleanup_handle(handle);
+    free(handle);
+  }
+
+  return 0;
+}
+
+const char *usb_name(usb_handle* handle) {
+  if (NULL == handle) {
+    SetLastError(ERROR_INVALID_HANDLE);
+    errno = ERROR_INVALID_HANDLE;
+    return NULL;
+  }
+
+  return (const char*)handle->interface_name;
+}
+
+int recognized_device(usb_handle* handle) {
+  if (NULL == handle)
+    return 0;
+
+  // Check vendor and product id first
+  USB_DEVICE_DESCRIPTOR device_desc;
+
+  if (!AdbGetUsbDeviceDescriptor(handle->adb_interface,
+                                 &device_desc)) {
+    return 0;
+  }
+
+  // Then check interface properties
+  USB_INTERFACE_DESCRIPTOR interf_desc;
+
+  if (!AdbGetUsbInterfaceDescriptor(handle->adb_interface,
+                                    &interf_desc)) {
+    return 0;
+  }
+
+  // Must have two endpoints
+  if (2 != interf_desc.bNumEndpoints) {
+    return 0;
+  }
+
+  if (is_adb_interface(device_desc.idVendor, device_desc.idProduct,
+      interf_desc.bInterfaceClass, interf_desc.bInterfaceSubClass, interf_desc.bInterfaceProtocol)) {
+
+    if(interf_desc.bInterfaceProtocol == 0x01) {
+      AdbEndpointInformation endpoint_info;
+      // assuming zero is a valid bulk endpoint ID
+      if (AdbGetEndpointInformation(handle->adb_interface, 0, &endpoint_info)) {
+        handle->zero_mask = endpoint_info.max_packet_size - 1;
+      }
+    }
+
+    return 1;
+  }
+
+  return 0;
+}
+
+void find_devices() {
+        usb_handle* handle = NULL;
+  char entry_buffer[2048];
+  char interf_name[2048];
+  AdbInterfaceInfo* next_interface = (AdbInterfaceInfo*)(&entry_buffer[0]);
+  unsigned long entry_buffer_size = sizeof(entry_buffer);
+  char* copy_name;
+
+  // Enumerate all present and active interfaces.
+  ADBAPIHANDLE enum_handle =
+    AdbEnumInterfaces(usb_class_id, true, true, true);
+
+  if (NULL == enum_handle)
+    return;
+
+  while (AdbNextInterface(enum_handle, next_interface, &entry_buffer_size)) {
+    // TODO: FIXME - temp hack converting wchar_t into char.
+    // It would be better to change AdbNextInterface so it will return
+    // interface name as single char string.
+    const wchar_t* wchar_name = next_interface->device_name;
+    for(copy_name = interf_name;
+        L'\0' != *wchar_name;
+        wchar_name++, copy_name++) {
+      *copy_name = (char)(*wchar_name);
+    }
+    *copy_name = '\0';
+
+    // Lets see if we already have this device in the list
+    if (!known_device(interf_name)) {
+      // This seems to be a new device. Open it!
+        handle = do_usb_open(next_interface->device_name);
+        if (NULL != handle) {
+        // Lets see if this interface (device) belongs to us
+        if (recognized_device(handle)) {
+          D("adding a new device %s\n", interf_name);
+          char serial_number[512];
+          unsigned long serial_number_len = sizeof(serial_number);
+          if (AdbGetSerialNumber(handle->adb_interface,
+                                serial_number,
+                                &serial_number_len,
+                                true)) {
+            // Lets make sure that we don't duplicate this device
+            if (register_new_device(handle)) {
+              register_usb_transport(handle, serial_number, NULL, 1);
+            } else {
+              D("register_new_device failed for %s\n", interf_name);
+              usb_cleanup_handle(handle);
+              free(handle);
+            }
+          } else {
+            D("cannot get serial number\n");
+            usb_cleanup_handle(handle);
+            free(handle);
+          }
+        } else {
+          usb_cleanup_handle(handle);
+          free(handle);
+        }
+      }
+    }
+
+    entry_buffer_size = sizeof(entry_buffer);
+  }
+
+  AdbCloseHandle(enum_handle);
+}
diff --git a/package/utils/adbd/src/include/android/log.h b/package/utils/adbd/src/include/android/log.h
new file mode 100644
index 0000000..1c171b7
--- /dev/null
+++ b/package/utils/adbd/src/include/android/log.h
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2009 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 _ANDROID_LOG_H
+#define _ANDROID_LOG_H
+
+/******************************************************************
+ *
+ * IMPORTANT NOTICE:
+ *
+ *   This file is part of Android's set of stable system headers
+ *   exposed by the Android NDK (Native Development Kit) since
+ *   platform release 1.5
+ *
+ *   Third-party source AND binary code relies on the definitions
+ *   here to be FROZEN ON ALL UPCOMING PLATFORM RELEASES.
+ *
+ *   - DO NOT MODIFY ENUMS (EXCEPT IF YOU ADD NEW 32-BIT VALUES)
+ *   - DO NOT MODIFY CONSTANTS OR FUNCTIONAL MACROS
+ *   - DO NOT CHANGE THE SIGNATURE OF FUNCTIONS IN ANY WAY
+ *   - DO NOT CHANGE THE LAYOUT OR SIZE OF STRUCTURES
+ */
+
+/*
+ * Support routines to send messages to the Android in-kernel log buffer,
+ * which can later be accessed through the 'logcat' utility.
+ *
+ * Each log message must have
+ *   - a priority
+ *   - a log tag
+ *   - some text
+ *
+ * The tag normally corresponds to the component that emits the log message,
+ * and should be reasonably small.
+ *
+ * Log message text may be truncated to less than an implementation-specific
+ * limit (e.g. 1023 characters max).
+ *
+ * Note that a newline character ("\n") will be appended automatically to your
+ * log message, if not already there. It is not possible to send several messages
+ * and have them appear on a single line in logcat.
+ *
+ * PLEASE USE LOGS WITH MODERATION:
+ *
+ *  - Sending log messages eats CPU and slow down your application and the
+ *    system.
+ *
+ *  - The circular log buffer is pretty small (<64KB), sending many messages
+ *    might push off other important log messages from the rest of the system.
+ *
+ *  - In release builds, only send log messages to account for exceptional
+ *    conditions.
+ *
+ * NOTE: These functions MUST be implemented by /system/lib/liblog.so
+ */
+
+#include <stdarg.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Android log priority values, in ascending priority order.
+ */
+typedef enum android_LogPriority {
+    ANDROID_LOG_UNKNOWN = 0,
+    ANDROID_LOG_DEFAULT,    /* only for SetMinPriority() */
+    ANDROID_LOG_VERBOSE,
+    ANDROID_LOG_DEBUG,
+    ANDROID_LOG_INFO,
+    ANDROID_LOG_WARN,
+    ANDROID_LOG_ERROR,
+    ANDROID_LOG_FATAL,
+    ANDROID_LOG_SILENT,     /* only for SetMinPriority(); must be last */
+} android_LogPriority;
+
+/*
+ * Send a simple string to the log.
+ */
+int __android_log_write(int prio, const char *tag, const char *text);
+
+/*
+ * Send a formatted string to the log, used like printf(fmt,...)
+ */
+int __android_log_print(int prio, const char *tag,  const char *fmt, ...)
+#if defined(__GNUC__)
+#ifdef __USE_MINGW_ANSI_STDIO
+#if __USE_MINGW_ANSI_STDIO
+    __attribute__ ((format(gnu_printf, 3, 4)))
+#else
+    __attribute__ ((format(printf, 3, 4)))
+#endif
+#else
+    __attribute__ ((format(printf, 3, 4)))
+#endif
+#endif
+    ;
+
+/*
+ * A variant of __android_log_print() that takes a va_list to list
+ * additional parameters.
+ */
+int __android_log_vprint(int prio, const char *tag,
+                         const char *fmt, va_list ap);
+
+/*
+ * Log an assertion failure and abort the process to have a chance
+ * to inspect it if a debugger is attached. This uses the FATAL priority.
+ */
+void __android_log_assert(const char *cond, const char *tag,
+                          const char *fmt, ...)
+#if defined(__GNUC__)
+    __attribute__ ((noreturn))
+#ifdef __USE_MINGW_ANSI_STDIO
+#if __USE_MINGW_ANSI_STDIO
+    __attribute__ ((format(gnu_printf, 3, 4)))
+#else
+    __attribute__ ((format(printf, 3, 4)))
+#endif
+#else
+    __attribute__ ((format(printf, 3, 4)))
+#endif
+#endif
+    ;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ANDROID_LOG_H */
diff --git a/package/utils/adbd/src/include/backtrace/Backtrace.h b/package/utils/adbd/src/include/backtrace/Backtrace.h
new file mode 100644
index 0000000..e07d322
--- /dev/null
+++ b/package/utils/adbd/src/include/backtrace/Backtrace.h
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2013 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 _BACKTRACE_BACKTRACE_H
+#define _BACKTRACE_BACKTRACE_H
+
+#include <inttypes.h>
+#include <stdint.h>
+
+#include <string>
+#include <vector>
+
+#include <backtrace/backtrace_constants.h>
+#include <backtrace/BacktraceMap.h>
+
+#if __LP64__
+#define PRIPTR "016" PRIxPTR
+typedef uint64_t word_t;
+#else
+#define PRIPTR "08" PRIxPTR
+typedef uint32_t word_t;
+#endif
+
+struct backtrace_frame_data_t {
+  size_t num;             // The current fame number.
+  uintptr_t pc;           // The absolute pc.
+  uintptr_t sp;           // The top of the stack.
+  size_t stack_size;      // The size of the stack, zero indicate an unknown stack size.
+  const backtrace_map_t* map;   // The map associated with the given pc.
+  std::string func_name;  // The function name associated with this pc, NULL if not found.
+  uintptr_t func_offset;  // pc relative to the start of the function, only valid if func_name is not NULL.
+};
+
+// Forward declarations.
+class BacktraceImpl;
+
+#if defined(__APPLE__)
+struct __darwin_ucontext;
+typedef __darwin_ucontext ucontext_t;
+#else
+struct ucontext;
+typedef ucontext ucontext_t;
+#endif
+
+class Backtrace {
+public:
+  // Create the correct Backtrace object based on what is to be unwound.
+  // If pid < 0 or equals the current pid, then the Backtrace object
+  // corresponds to the current process.
+  // If pid < 0 or equals the current pid and tid >= 0, then the Backtrace
+  // object corresponds to a thread in the current process.
+  // If pid >= 0 and tid < 0, then the Backtrace object corresponds to a
+  // different process.
+  // Tracing a thread in a different process is not supported.
+  // If map is NULL, then create the map and manage it internally.
+  // If map is not NULL, the map is still owned by the caller.
+  static Backtrace* Create(pid_t pid, pid_t tid, BacktraceMap* map = NULL);
+
+  virtual ~Backtrace();
+
+  // Get the current stack trace and store in the backtrace_ structure.
+  virtual bool Unwind(size_t num_ignore_frames, ucontext_t* context = NULL);
+
+  // Get the function name and offset into the function given the pc.
+  // If the string is empty, then no valid function name was found.
+  virtual std::string GetFunctionName(uintptr_t pc, uintptr_t* offset);
+
+  // Find the map associated with the given pc.
+  virtual const backtrace_map_t* FindMap(uintptr_t pc);
+
+  // Read the data at a specific address.
+  virtual bool ReadWord(uintptr_t ptr, word_t* out_value) = 0;
+
+  // Create a string representing the formatted line of backtrace information
+  // for a single frame.
+  virtual std::string FormatFrameData(size_t frame_num);
+  virtual std::string FormatFrameData(const backtrace_frame_data_t* frame);
+
+  pid_t Pid() { return pid_; }
+  pid_t Tid() { return tid_; }
+  size_t NumFrames() { return frames_.size(); }
+
+  const backtrace_frame_data_t* GetFrame(size_t frame_num) {
+    if (frame_num >= frames_.size()) {
+      return NULL;
+    }
+    return &frames_[frame_num];
+  }
+
+  typedef std::vector<backtrace_frame_data_t>::iterator iterator;
+  iterator begin() { return frames_.begin(); }
+  iterator end() { return frames_.end(); }
+
+  typedef std::vector<backtrace_frame_data_t>::const_iterator const_iterator;
+  const_iterator begin() const { return frames_.begin(); }
+  const_iterator end() const { return frames_.end(); }
+
+  BacktraceMap* GetMap() { return map_; }
+
+protected:
+  Backtrace(BacktraceImpl* impl, pid_t pid, BacktraceMap* map);
+
+  virtual bool VerifyReadWordArgs(uintptr_t ptr, word_t* out_value);
+
+  bool BuildMap();
+
+  pid_t pid_;
+  pid_t tid_;
+
+  BacktraceMap* map_;
+  bool map_shared_;
+
+  std::vector<backtrace_frame_data_t> frames_;
+
+  BacktraceImpl* impl_;
+
+  friend class BacktraceImpl;
+};
+
+#endif // _BACKTRACE_BACKTRACE_H
diff --git a/package/utils/adbd/src/include/backtrace/BacktraceMap.h b/package/utils/adbd/src/include/backtrace/BacktraceMap.h
new file mode 100644
index 0000000..c717f09
--- /dev/null
+++ b/package/utils/adbd/src/include/backtrace/BacktraceMap.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2014 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 _BACKTRACE_BACKTRACE_MAP_H
+#define _BACKTRACE_BACKTRACE_MAP_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#ifdef USE_MINGW
+// MINGW does not define these constants.
+#define PROT_NONE 0
+#define PROT_READ 0x1
+#define PROT_WRITE 0x2
+#define PROT_EXEC 0x4
+#else
+#include <sys/mman.h>
+#endif
+
+#include <deque>
+#include <string>
+
+struct backtrace_map_t {
+  uintptr_t start;
+  uintptr_t end;
+  int flags;
+  std::string name;
+};
+
+class BacktraceMap {
+public:
+  static BacktraceMap* Create(pid_t pid);
+
+  virtual ~BacktraceMap();
+
+  // Get the map data structure for the given address.
+  virtual const backtrace_map_t* Find(uintptr_t addr);
+
+  // The flags returned are the same flags as used by the mmap call.
+  // The values are PROT_*.
+  int GetFlags(uintptr_t pc) {
+    const backtrace_map_t* map = Find(pc);
+    if (map) {
+      return map->flags;
+    }
+    return PROT_NONE;
+  }
+
+  bool IsReadable(uintptr_t pc) { return GetFlags(pc) & PROT_READ; }
+  bool IsWritable(uintptr_t pc) { return GetFlags(pc) & PROT_WRITE; }
+  bool IsExecutable(uintptr_t pc) { return GetFlags(pc) & PROT_EXEC; }
+
+  typedef std::deque<backtrace_map_t>::iterator iterator;
+  iterator begin() { return maps_.begin(); }
+  iterator end() { return maps_.end(); }
+
+  typedef std::deque<backtrace_map_t>::const_iterator const_iterator;
+  const_iterator begin() const { return maps_.begin(); }
+  const_iterator end() const { return maps_.end(); }
+
+  virtual bool Build();
+
+protected:
+  BacktraceMap(pid_t pid);
+
+  virtual bool ParseLine(const char* line, backtrace_map_t* map);
+
+  std::deque<backtrace_map_t> maps_;
+  pid_t pid_;
+};
+
+#endif // _BACKTRACE_BACKTRACE_MAP_H
diff --git a/package/utils/adbd/src/include/backtrace/backtrace_constants.h b/package/utils/adbd/src/include/backtrace/backtrace_constants.h
new file mode 100644
index 0000000..f8c1575
--- /dev/null
+++ b/package/utils/adbd/src/include/backtrace/backtrace_constants.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2014 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 _BACKTRACE_BACKTRACE_CONSTANTS_H
+#define _BACKTRACE_BACKTRACE_CONSTANTS_H
+
+// When the pid to be traced is set to this value, then trace the current
+// process. If the tid value is not BACKTRACE_NO_TID, then the specified
+// thread from the current process will be traced.
+#define BACKTRACE_CURRENT_PROCESS -1
+// When the tid to be traced is set to this value, then trace the specified
+// current thread of the specified pid.
+#define BACKTRACE_CURRENT_THREAD -1
+
+#define MAX_BACKTRACE_FRAMES 64
+
+#endif // _BACKTRACE_BACKTRACE_CONSTANTS_H
diff --git a/package/utils/adbd/src/include/ctest/ctest.h b/package/utils/adbd/src/include/ctest/ctest.h
new file mode 100644
index 0000000..1a83b20
--- /dev/null
+++ b/package/utils/adbd/src/include/ctest/ctest.h
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ */
+
+/**
+ * Very simple unit testing framework. 
+ */
+
+#ifndef __CUTILS_TEST_H
+#define __CUTILS_TEST_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Adds a test to the test suite.
+ */
+#define addTest(test) addNamedTest(#test, &test)
+   
+/**
+ * Asserts that a condition is true. The test fails if it isn't.
+ */
+#define assertTrue(value, message) assertTrueWithSource(value, __FILE__, __LINE__, message);
+
+/**
+ * Asserts that a condition is false. The test fails if the value is true.
+ */
+#define assertFalse(value, message) assertTrueWithSource(!value, __FILE__, __LINE__, message);
+
+/** Fails a test with the given message. */
+#define fail(message) assertTrueWithSource(0, __FILE__, __LINE__, message);
+
+/**
+ * Asserts that two values are ==.
+ */
+#define assertSame(a, b) assertTrueWithSource(a == b, __FILE__, __LINE__, "Expected same value.");
+    
+/**
+ * Asserts that two values are !=.
+ */
+#define assertNotSame(a, b) assertTrueWithSource(a != b, __FILE__, __LINE__,\
+        "Expected different values");
+    
+/**
+ * Runs a test suite.
+ */
+void runTests(void);
+
+// Do not call these functions directly. Use macros above instead.
+void addNamedTest(const char* name, void (*test)(void));
+void assertTrueWithSource(int value, const char* file, int line, char* message);
+    
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CUTILS_TEST_H */ 
diff --git a/package/utils/adbd/src/include/cutils/android_reboot.h b/package/utils/adbd/src/include/cutils/android_reboot.h
new file mode 100644
index 0000000..3d91846
--- /dev/null
+++ b/package/utils/adbd/src/include/cutils/android_reboot.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2011, 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 __CUTILS_ANDROID_REBOOT_H__
+#define __CUTILS_ANDROID_REBOOT_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Commands */
+#define ANDROID_RB_RESTART  0xDEAD0001
+#define ANDROID_RB_POWEROFF 0xDEAD0002
+#define ANDROID_RB_RESTART2 0xDEAD0003
+
+/* Properties */
+#define ANDROID_RB_PROPERTY "sys.powerctl"
+
+int android_reboot(int cmd, int flags, char *arg);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __CUTILS_ANDROID_REBOOT_H__ */
diff --git a/package/utils/adbd/src/include/cutils/aref.h b/package/utils/adbd/src/include/cutils/aref.h
new file mode 100644
index 0000000..fc7e1b0
--- /dev/null
+++ b/package/utils/adbd/src/include/cutils/aref.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2013 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 _CUTILS_AREF_H_
+#define _CUTILS_AREF_H_
+
+#include <stddef.h>
+
+#ifdef ANDROID_SMP
+#include <cutils/atomic-inline.h>
+#else
+#include <cutils/atomic.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define AREF_TO_ITEM(aref, container, member) \
+    (container *) (((char*) (aref)) - offsetof(container, member))
+
+struct aref
+{
+    volatile int32_t count;
+};
+
+static inline void aref_init(struct aref *r)
+{
+    r->count = 1;
+}
+
+static inline int32_t aref_count(struct aref *r)
+{
+    return r->count;
+}
+
+static inline void aref_get(struct aref *r)
+{
+    android_atomic_inc(&r->count);
+}
+
+static inline void aref_put(struct aref *r, void (*release)(struct aref *))
+{
+    if (android_atomic_dec(&r->count) == 1)
+        release(r);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _CUTILS_AREF_H_
diff --git a/package/utils/adbd/src/include/cutils/ashmem.h b/package/utils/adbd/src/include/cutils/ashmem.h
new file mode 100644
index 0000000..25b233e
--- /dev/null
+++ b/package/utils/adbd/src/include/cutils/ashmem.h
@@ -0,0 +1,45 @@
+/* cutils/ashmem.h
+ **
+ ** Copyright 2008 The Android Open Source Project
+ **
+ ** This file is dual licensed.  It may be redistributed and/or modified
+ ** under the terms of the Apache 2.0 License OR version 2 of the GNU
+ ** General Public License.
+ */
+
+#ifndef _CUTILS_ASHMEM_H
+#define _CUTILS_ASHMEM_H
+
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int ashmem_create_region(const char *name, size_t size);
+int ashmem_set_prot_region(int fd, int prot);
+int ashmem_pin_region(int fd, size_t offset, size_t len);
+int ashmem_unpin_region(int fd, size_t offset, size_t len);
+int ashmem_get_size_region(int fd);
+
+#ifdef __cplusplus
+}
+#endif
+
+#ifndef __ASHMEMIOC	/* in case someone included <linux/ashmem.h> too */
+
+#define ASHMEM_NAME_LEN		256
+
+#define ASHMEM_NAME_DEF		"dev/ashmem"
+
+/* Return values from ASHMEM_PIN: Was the mapping purged while unpinned? */
+#define ASHMEM_NOT_PURGED	0
+#define ASHMEM_WAS_PURGED	1
+
+/* Return values from ASHMEM_UNPIN: Is the mapping now pinned or unpinned? */
+#define ASHMEM_IS_UNPINNED	0
+#define ASHMEM_IS_PINNED	1
+
+#endif	/* ! __ASHMEMIOC */
+
+#endif	/* _CUTILS_ASHMEM_H */
diff --git a/package/utils/adbd/src/include/cutils/atomic-arm.h b/package/utils/adbd/src/include/cutils/atomic-arm.h
new file mode 100644
index 0000000..172a0cd
--- /dev/null
+++ b/package/utils/adbd/src/include/cutils/atomic-arm.h
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2010 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 ANDROID_CUTILS_ATOMIC_ARM_H
+#define ANDROID_CUTILS_ATOMIC_ARM_H
+
+#include <stdint.h>
+
+#ifndef ANDROID_ATOMIC_INLINE
+#define ANDROID_ATOMIC_INLINE inline __attribute__((always_inline))
+#endif
+
+extern ANDROID_ATOMIC_INLINE void android_compiler_barrier()
+{
+    __asm__ __volatile__ ("" : : : "memory");
+}
+
+extern ANDROID_ATOMIC_INLINE void android_memory_barrier()
+{
+#if ANDROID_SMP == 0
+    android_compiler_barrier();
+#else
+    __asm__ __volatile__ ("dmb" : : : "memory");
+#endif
+}
+
+extern ANDROID_ATOMIC_INLINE void android_memory_store_barrier()
+{
+#if ANDROID_SMP == 0
+    android_compiler_barrier();
+#else
+    __asm__ __volatile__ ("dmb st" : : : "memory");
+#endif
+}
+
+extern ANDROID_ATOMIC_INLINE
+int32_t android_atomic_acquire_load(volatile const int32_t *ptr)
+{
+    int32_t value = *ptr;
+    android_memory_barrier();
+    return value;
+}
+
+extern ANDROID_ATOMIC_INLINE
+int32_t android_atomic_release_load(volatile const int32_t *ptr)
+{
+    android_memory_barrier();
+    return *ptr;
+}
+
+extern ANDROID_ATOMIC_INLINE
+void android_atomic_acquire_store(int32_t value, volatile int32_t *ptr)
+{
+    *ptr = value;
+    android_memory_barrier();
+}
+
+extern ANDROID_ATOMIC_INLINE
+void android_atomic_release_store(int32_t value, volatile int32_t *ptr)
+{
+    android_memory_barrier();
+    *ptr = value;
+}
+
+extern ANDROID_ATOMIC_INLINE
+int android_atomic_cas(int32_t old_value, int32_t new_value,
+                       volatile int32_t *ptr)
+{
+    int32_t prev, status;
+    do {
+        __asm__ __volatile__ ("ldrex %0, [%3]\n"
+                              "mov %1, #0\n"
+                              "teq %0, %4\n"
+#ifdef __thumb2__
+                              "it eq\n"
+#endif
+                              "strexeq %1, %5, [%3]"
+                              : "=&r" (prev), "=&r" (status), "+m"(*ptr)
+                              : "r" (ptr), "Ir" (old_value), "r" (new_value)
+                              : "cc");
+    } while (__builtin_expect(status != 0, 0));
+    return prev != old_value;
+}
+
+extern ANDROID_ATOMIC_INLINE
+int android_atomic_acquire_cas(int32_t old_value, int32_t new_value,
+                               volatile int32_t *ptr)
+{
+    int status = android_atomic_cas(old_value, new_value, ptr);
+    android_memory_barrier();
+    return status;
+}
+
+extern ANDROID_ATOMIC_INLINE
+int android_atomic_release_cas(int32_t old_value, int32_t new_value,
+                               volatile int32_t *ptr)
+{
+    android_memory_barrier();
+    return android_atomic_cas(old_value, new_value, ptr);
+}
+
+extern ANDROID_ATOMIC_INLINE
+int32_t android_atomic_add(int32_t increment, volatile int32_t *ptr)
+{
+    int32_t prev, tmp, status;
+    android_memory_barrier();
+    do {
+        __asm__ __volatile__ ("ldrex %0, [%4]\n"
+                              "add %1, %0, %5\n"
+                              "strex %2, %1, [%4]"
+                              : "=&r" (prev), "=&r" (tmp),
+                                "=&r" (status), "+m" (*ptr)
+                              : "r" (ptr), "Ir" (increment)
+                              : "cc");
+    } while (__builtin_expect(status != 0, 0));
+    return prev;
+}
+
+extern ANDROID_ATOMIC_INLINE int32_t android_atomic_inc(volatile int32_t *addr)
+{
+    return android_atomic_add(1, addr);
+}
+
+extern ANDROID_ATOMIC_INLINE int32_t android_atomic_dec(volatile int32_t *addr)
+{
+    return android_atomic_add(-1, addr);
+}
+
+extern ANDROID_ATOMIC_INLINE
+int32_t android_atomic_and(int32_t value, volatile int32_t *ptr)
+{
+    int32_t prev, tmp, status;
+    android_memory_barrier();
+    do {
+        __asm__ __volatile__ ("ldrex %0, [%4]\n"
+                              "and %1, %0, %5\n"
+                              "strex %2, %1, [%4]"
+                              : "=&r" (prev), "=&r" (tmp),
+                                "=&r" (status), "+m" (*ptr)
+                              : "r" (ptr), "Ir" (value)
+                              : "cc");
+    } while (__builtin_expect(status != 0, 0));
+    return prev;
+}
+
+extern ANDROID_ATOMIC_INLINE
+int32_t android_atomic_or(int32_t value, volatile int32_t *ptr)
+{
+    int32_t prev, tmp, status;
+    android_memory_barrier();
+    do {
+        __asm__ __volatile__ ("ldrex %0, [%4]\n"
+                              "orr %1, %0, %5\n"
+                              "strex %2, %1, [%4]"
+                              : "=&r" (prev), "=&r" (tmp),
+                                "=&r" (status), "+m" (*ptr)
+                              : "r" (ptr), "Ir" (value)
+                              : "cc");
+    } while (__builtin_expect(status != 0, 0));
+    return prev;
+}
+
+#endif /* ANDROID_CUTILS_ATOMIC_ARM_H */
diff --git a/package/utils/adbd/src/include/cutils/atomic-arm64.h b/package/utils/adbd/src/include/cutils/atomic-arm64.h
new file mode 100644
index 0000000..4562ad0
--- /dev/null
+++ b/package/utils/adbd/src/include/cutils/atomic-arm64.h
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef ANDROID_CUTILS_ATOMIC_AARCH64_H
+#define ANDROID_CUTILS_ATOMIC_AARCH64_H
+
+#include <stdint.h>
+
+#ifndef ANDROID_ATOMIC_INLINE
+#define ANDROID_ATOMIC_INLINE inline __attribute__((always_inline))
+#endif
+
+/*
+   TODOAArch64: Revisit the below functions and check for potential
+   optimizations using assembly code or otherwise.
+*/
+
+extern ANDROID_ATOMIC_INLINE
+void android_compiler_barrier(void)
+{
+    __asm__ __volatile__ ("" : : : "memory");
+}
+
+#if ANDROID_SMP == 0
+extern ANDROID_ATOMIC_INLINE
+void android_memory_barrier(void)
+{
+    android_compiler_barrier();
+}
+extern ANDROID_ATOMIC_INLINE
+void android_memory_store_barrier(void)
+{
+    android_compiler_barrier();
+}
+#else
+extern ANDROID_ATOMIC_INLINE
+void android_memory_barrier(void)
+{
+    __asm__ __volatile__ ("dmb ish" : : : "memory");
+}
+extern ANDROID_ATOMIC_INLINE
+void android_memory_store_barrier(void)
+{
+    __asm__ __volatile__ ("dmb ishst" : : : "memory");
+}
+#endif
+
+extern ANDROID_ATOMIC_INLINE
+int32_t android_atomic_acquire_load(volatile const int32_t *ptr)
+{
+    int32_t value = *ptr;
+    android_memory_barrier();
+    return value;
+}
+
+extern ANDROID_ATOMIC_INLINE
+int64_t android_atomic_acquire_load64(volatile const int64_t *ptr)
+{
+    int64_t value = *ptr;
+    android_memory_barrier();
+    return value;
+}
+
+extern ANDROID_ATOMIC_INLINE
+int32_t android_atomic_release_load(volatile const int32_t *ptr)
+{
+    android_memory_barrier();
+    return *ptr;
+}
+
+extern ANDROID_ATOMIC_INLINE
+int64_t android_atomic_release_load64(volatile const int64_t *ptr)
+{
+    android_memory_barrier();
+    return *ptr;
+}
+
+extern ANDROID_ATOMIC_INLINE
+void android_atomic_acquire_store(int32_t value, volatile int32_t *ptr)
+{
+    *ptr = value;
+    android_memory_barrier();
+}
+
+extern ANDROID_ATOMIC_INLINE
+void android_atomic_acquire_store64(int64_t value, volatile int64_t *ptr)
+{
+    *ptr = value;
+    android_memory_barrier();
+}
+
+extern ANDROID_ATOMIC_INLINE
+void android_atomic_release_store(int32_t value, volatile int32_t *ptr)
+{
+    android_memory_barrier();
+    *ptr = value;
+}
+
+extern ANDROID_ATOMIC_INLINE
+void android_atomic_release_store64(int64_t value, volatile int64_t *ptr)
+{
+    android_memory_barrier();
+    *ptr = value;
+}
+
+extern ANDROID_ATOMIC_INLINE
+int android_atomic_cas(int32_t old_value, int32_t new_value,
+                       volatile int32_t *ptr)
+{
+    return __sync_val_compare_and_swap(ptr, old_value, new_value) != old_value;
+}
+
+extern ANDROID_ATOMIC_INLINE
+int64_t android_atomic_cas64(int64_t old_value, int64_t new_value,
+                             volatile int64_t *ptr)
+{
+    return __sync_val_compare_and_swap(ptr, old_value, new_value) != old_value;
+}
+
+extern ANDROID_ATOMIC_INLINE
+int android_atomic_acquire_cas(int32_t old_value, int32_t new_value,
+                               volatile int32_t *ptr)
+{
+    int status = android_atomic_cas(old_value, new_value, ptr);
+    android_memory_barrier();
+    return status;
+}
+
+extern ANDROID_ATOMIC_INLINE
+int64_t android_atomic_acquire_cas64(int64_t old_value, int64_t new_value,
+                                     volatile int64_t *ptr)
+{
+    int status = android_atomic_cas64(old_value, new_value, ptr);
+    android_memory_barrier();
+    return status;
+}
+
+extern ANDROID_ATOMIC_INLINE
+int android_atomic_release_cas(int32_t old_value, int32_t new_value,
+                               volatile int32_t *ptr)
+{
+    android_memory_barrier();
+    return android_atomic_cas(old_value, new_value, ptr);
+}
+
+extern ANDROID_ATOMIC_INLINE
+int64_t android_atomic_release_cas64(int64_t old_value, int64_t new_value,
+                                     volatile int64_t *ptr)
+{
+    android_memory_barrier();
+    return android_atomic_cas64(old_value, new_value, ptr);
+}
+
+extern ANDROID_ATOMIC_INLINE
+int32_t android_atomic_add(int32_t increment, volatile int32_t *ptr)
+{
+    int32_t prev, status;
+    android_memory_barrier();
+    do {
+        prev = *ptr;
+        status = android_atomic_cas(prev, prev + increment, ptr);
+    } while (__builtin_expect(status != 0, 0));
+    return prev;
+}
+
+extern ANDROID_ATOMIC_INLINE
+int32_t android_atomic_inc(volatile int32_t *addr)
+{
+    return android_atomic_add(1, addr);
+}
+
+extern ANDROID_ATOMIC_INLINE
+int32_t android_atomic_dec(volatile int32_t *addr)
+{
+    return android_atomic_add(-1, addr);
+}
+
+extern ANDROID_ATOMIC_INLINE
+int32_t android_atomic_and(int32_t value, volatile int32_t *ptr)
+{
+    int32_t prev, status;
+    android_memory_barrier();
+    do {
+        prev = *ptr;
+        status = android_atomic_cas(prev, prev & value, ptr);
+    } while (__builtin_expect(status != 0, 0));
+    return prev;
+}
+
+extern ANDROID_ATOMIC_INLINE
+int32_t android_atomic_or(int32_t value, volatile int32_t *ptr)
+{
+    int32_t prev, status;
+    android_memory_barrier();
+    do {
+        prev = *ptr;
+        status = android_atomic_cas(prev, prev | value, ptr);
+    } while (__builtin_expect(status != 0, 0));
+    return prev;
+}
+
+#endif /* ANDROID_CUTILS_ATOMIC_AARCH64_H */
diff --git a/package/utils/adbd/src/include/cutils/atomic-inline.h b/package/utils/adbd/src/include/cutils/atomic-inline.h
new file mode 100644
index 0000000..007a905
--- /dev/null
+++ b/package/utils/adbd/src/include/cutils/atomic-inline.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2010 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 ANDROID_CUTILS_ATOMIC_INLINE_H
+#define ANDROID_CUTILS_ATOMIC_INLINE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Inline declarations and macros for some special-purpose atomic
+ * operations.  These are intended for rare circumstances where a
+ * memory barrier needs to be issued inline rather than as a function
+ * call.
+ *
+ * Most code should not use these.
+ *
+ * Anything that does include this file must set ANDROID_SMP to either
+ * 0 or 1, indicating compilation for UP or SMP, respectively.
+ *
+ * Macros defined in this header:
+ *
+ * void ANDROID_MEMBAR_FULL(void)
+ *   Full memory barrier.  Provides a compiler reordering barrier, and
+ *   on SMP systems emits an appropriate instruction.
+ */
+
+#if !defined(ANDROID_SMP)
+# error "Must define ANDROID_SMP before including atomic-inline.h"
+#endif
+
+#if defined(__aarch64__)
+#include <cutils/atomic-arm64.h>
+#elif defined(__arm__)
+#include <cutils/atomic-arm.h>
+#elif defined(__i386__)
+#include <cutils/atomic-x86.h>
+#elif defined(__x86_64__)
+#include <cutils/atomic-x86_64.h>
+#elif defined(__mips64)
+#include <cutils/atomic-mips64.h>
+#elif defined(__mips__)
+#include <cutils/atomic-mips.h>
+#else
+#error atomic operations are unsupported
+#endif
+
+#if ANDROID_SMP == 0
+#define ANDROID_MEMBAR_FULL android_compiler_barrier
+#else
+#define ANDROID_MEMBAR_FULL android_memory_barrier
+#endif
+
+#if ANDROID_SMP == 0
+#define ANDROID_MEMBAR_STORE android_compiler_barrier
+#else
+#define ANDROID_MEMBAR_STORE android_memory_store_barrier
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ANDROID_CUTILS_ATOMIC_INLINE_H */
diff --git a/package/utils/adbd/src/include/cutils/atomic-mips.h b/package/utils/adbd/src/include/cutils/atomic-mips.h
new file mode 100644
index 0000000..1ed833d
--- /dev/null
+++ b/package/utils/adbd/src/include/cutils/atomic-mips.h
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2010 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 ANDROID_CUTILS_ATOMIC_MIPS_H
+#define ANDROID_CUTILS_ATOMIC_MIPS_H
+
+#include <stdint.h>
+
+#ifndef ANDROID_ATOMIC_INLINE
+#define ANDROID_ATOMIC_INLINE inline __attribute__((always_inline))
+#endif
+
+extern ANDROID_ATOMIC_INLINE void android_compiler_barrier(void)
+{
+    __asm__ __volatile__ ("" : : : "memory");
+}
+
+#if ANDROID_SMP == 0
+extern ANDROID_ATOMIC_INLINE void android_memory_barrier(void)
+{
+    android_compiler_barrier();
+}
+extern ANDROID_ATOMIC_INLINE void android_memory_store_barrier(void)
+{
+    android_compiler_barrier();
+}
+#else
+extern ANDROID_ATOMIC_INLINE void android_memory_barrier(void)
+{
+    __asm__ __volatile__ ("sync" : : : "memory");
+}
+extern ANDROID_ATOMIC_INLINE void android_memory_store_barrier(void)
+{
+    __asm__ __volatile__ ("sync" : : : "memory");
+}
+#endif
+
+extern ANDROID_ATOMIC_INLINE int32_t
+android_atomic_acquire_load(volatile const int32_t *ptr)
+{
+    int32_t value = *ptr;
+    android_memory_barrier();
+    return value;
+}
+
+extern ANDROID_ATOMIC_INLINE int32_t
+android_atomic_release_load(volatile const int32_t *ptr)
+{
+    android_memory_barrier();
+    return *ptr;
+}
+
+extern ANDROID_ATOMIC_INLINE void
+android_atomic_acquire_store(int32_t value, volatile int32_t *ptr)
+{
+    *ptr = value;
+    android_memory_barrier();
+}
+
+extern ANDROID_ATOMIC_INLINE void
+android_atomic_release_store(int32_t value, volatile int32_t *ptr)
+{
+    android_memory_barrier();
+    *ptr = value;
+}
+
+extern ANDROID_ATOMIC_INLINE int
+android_atomic_cas(int32_t old_value, int32_t new_value, volatile int32_t *ptr)
+{
+    int32_t prev, status;
+    do {
+        __asm__ __volatile__ (
+            "    ll     %[prev], (%[ptr])\n"
+            "    li     %[status], 1\n"
+            "    bne    %[prev], %[old], 9f\n"
+            "    move   %[status], %[new_value]\n"
+            "    sc     %[status], (%[ptr])\n"
+            "9:\n"
+            : [prev] "=&r" (prev), [status] "=&r" (status)
+            : [ptr] "r" (ptr), [old] "r" (old_value), [new_value] "r" (new_value)
+            );
+    } while (__builtin_expect(status == 0, 0));
+    return prev != old_value;
+}
+
+extern ANDROID_ATOMIC_INLINE int
+android_atomic_acquire_cas(int32_t old_value,
+                           int32_t new_value,
+                           volatile int32_t *ptr)
+{
+    int status = android_atomic_cas(old_value, new_value, ptr);
+    android_memory_barrier();
+    return status;
+}
+
+extern ANDROID_ATOMIC_INLINE int
+android_atomic_release_cas(int32_t old_value,
+                           int32_t new_value,
+                           volatile int32_t *ptr)
+{
+    android_memory_barrier();
+    return android_atomic_cas(old_value, new_value, ptr);
+}
+
+
+extern ANDROID_ATOMIC_INLINE int32_t
+android_atomic_add(int32_t increment, volatile int32_t *ptr)
+{
+    int32_t prev, status;
+    android_memory_barrier();
+    do {
+        __asm__ __volatile__ (
+        "    ll    %[prev], (%[ptr])\n"
+        "    addu  %[status], %[prev], %[inc]\n"
+        "    sc    %[status], (%[ptr])\n"
+        :  [status] "=&r" (status), [prev] "=&r" (prev)
+        :  [ptr] "r" (ptr), [inc] "Ir" (increment)
+        );
+    } while (__builtin_expect(status == 0, 0));
+    return prev;
+}
+
+extern ANDROID_ATOMIC_INLINE int32_t
+android_atomic_inc(volatile int32_t *addr)
+{
+    return android_atomic_add(1, addr);
+}
+
+extern ANDROID_ATOMIC_INLINE int32_t
+android_atomic_dec(volatile int32_t *addr)
+{
+    return android_atomic_add(-1, addr);
+}
+
+extern ANDROID_ATOMIC_INLINE int32_t
+android_atomic_and(int32_t value, volatile int32_t *ptr)
+{
+    int32_t prev, status;
+    android_memory_barrier();
+    do {
+        __asm__ __volatile__ (
+        "    ll    %[prev], (%[ptr])\n"
+        "    and   %[status], %[prev], %[value]\n"
+        "    sc    %[status], (%[ptr])\n"
+        : [prev] "=&r" (prev), [status] "=&r" (status)
+        : [ptr] "r" (ptr), [value] "Ir" (value)
+            );
+    } while (__builtin_expect(status == 0, 0));
+    return prev;
+}
+
+extern ANDROID_ATOMIC_INLINE int32_t
+android_atomic_or(int32_t value, volatile int32_t *ptr)
+{
+    int32_t prev, status;
+    android_memory_barrier();
+    do {
+        __asm__ __volatile__ (
+        "    ll    %[prev], (%[ptr])\n"
+        "    or    %[status], %[prev], %[value]\n"
+        "    sc    %[status], (%[ptr])\n"
+        : [prev] "=&r" (prev), [status] "=&r" (status)
+        : [ptr] "r" (ptr), [value] "Ir" (value)
+            );
+    } while (__builtin_expect(status == 0, 0));
+    return prev;
+}
+
+#endif /* ANDROID_CUTILS_ATOMIC_MIPS_H */
diff --git a/package/utils/adbd/src/include/cutils/atomic-mips64.h b/package/utils/adbd/src/include/cutils/atomic-mips64.h
new file mode 100644
index 0000000..99bbe3a
--- /dev/null
+++ b/package/utils/adbd/src/include/cutils/atomic-mips64.h
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2010 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 ANDROID_CUTILS_ATOMIC_MIPS64_H
+#define ANDROID_CUTILS_ATOMIC_MIPS64_H
+
+#include <stdint.h>
+
+#ifndef ANDROID_ATOMIC_INLINE
+#define ANDROID_ATOMIC_INLINE inline __attribute__((always_inline))
+#endif
+
+extern ANDROID_ATOMIC_INLINE void android_compiler_barrier(void)
+{
+    __asm__ __volatile__ ("" : : : "memory");
+}
+
+#if ANDROID_SMP == 0
+extern ANDROID_ATOMIC_INLINE void android_memory_barrier(void)
+{
+    android_compiler_barrier();
+}
+extern ANDROID_ATOMIC_INLINE void android_memory_store_barrier(void)
+{
+    android_compiler_barrier();
+}
+#else
+extern ANDROID_ATOMIC_INLINE void android_memory_barrier(void)
+{
+    __asm__ __volatile__ ("sync" : : : "memory");
+}
+extern ANDROID_ATOMIC_INLINE void android_memory_store_barrier(void)
+{
+    __asm__ __volatile__ ("sync" : : : "memory");
+}
+#endif
+
+extern ANDROID_ATOMIC_INLINE
+int32_t android_atomic_acquire_load(volatile const int32_t *ptr)
+{
+    int32_t value = *ptr;
+    android_memory_barrier();
+    return value;
+}
+
+extern ANDROID_ATOMIC_INLINE
+int64_t android_atomic_acquire_load64(volatile const int64_t *ptr)
+{
+    int64_t value = *ptr;
+    android_memory_barrier();
+    return value;
+}
+
+extern ANDROID_ATOMIC_INLINE
+int32_t android_atomic_release_load(volatile const int32_t *ptr)
+{
+    android_memory_barrier();
+    return *ptr;
+}
+
+extern ANDROID_ATOMIC_INLINE
+int64_t android_atomic_release_load64(volatile const int64_t *ptr)
+{
+    android_memory_barrier();
+    return *ptr;
+}
+
+extern ANDROID_ATOMIC_INLINE
+void android_atomic_acquire_store(int32_t value, volatile int32_t *ptr)
+{
+    *ptr = value;
+    android_memory_barrier();
+}
+
+extern ANDROID_ATOMIC_INLINE
+void android_atomic_acquire_store64(int64_t value, volatile int64_t *ptr)
+{
+    *ptr = value;
+    android_memory_barrier();
+}
+
+extern ANDROID_ATOMIC_INLINE
+void android_atomic_release_store(int32_t value, volatile int32_t *ptr)
+{
+    android_memory_barrier();
+    *ptr = value;
+}
+
+extern ANDROID_ATOMIC_INLINE
+void android_atomic_release_store64(int64_t value, volatile int64_t *ptr)
+{
+    android_memory_barrier();
+    *ptr = value;
+}
+
+extern ANDROID_ATOMIC_INLINE
+int android_atomic_cas(int32_t old_value, int32_t new_value, volatile int32_t *ptr)
+{
+    int32_t prev, status;
+    do {
+        __asm__ __volatile__ (
+            "    ll     %[prev], (%[ptr])\n"
+            "    li     %[status], 1\n"
+            "    bne    %[prev], %[old], 9f\n"
+            "    move   %[status], %[new_value]\n"
+            "    sc     %[status], (%[ptr])\n"
+            "9:\n"
+            : [prev] "=&r" (prev), [status] "=&r" (status)
+            : [ptr] "r" (ptr), [old] "r" (old_value), [new_value] "r" (new_value)
+            );
+    } while (__builtin_expect(status == 0, 0));
+    return prev != old_value;
+}
+
+extern ANDROID_ATOMIC_INLINE
+int64_t android_atomic_cas64(int64_t old_value, int64_t new_value,
+                             volatile int64_t *ptr)
+{
+    return __sync_val_compare_and_swap(ptr, old_value, new_value) != old_value;
+}
+
+extern ANDROID_ATOMIC_INLINE
+int android_atomic_acquire_cas(int32_t old_value,
+                           int32_t new_value,
+                           volatile int32_t *ptr)
+{
+    int status = android_atomic_cas(old_value, new_value, ptr);
+    android_memory_barrier();
+    return status;
+}
+
+extern ANDROID_ATOMIC_INLINE
+int64_t android_atomic_acquire_cas64(int64_t old_value, int64_t new_value,
+                                     volatile int64_t *ptr)
+{
+    int status = android_atomic_cas64(old_value, new_value, ptr);
+    android_memory_barrier();
+    return status;
+}
+
+extern ANDROID_ATOMIC_INLINE
+int android_atomic_release_cas(int32_t old_value,
+                           int32_t new_value,
+                           volatile int32_t *ptr)
+{
+    android_memory_barrier();
+    return android_atomic_cas(old_value, new_value, ptr);
+}
+
+extern ANDROID_ATOMIC_INLINE
+int64_t android_atomic_release_cas64(int64_t old_value, int64_t new_value,
+                                     volatile int64_t *ptr)
+{
+    android_memory_barrier();
+    return android_atomic_cas64(old_value, new_value, ptr);
+}
+
+extern ANDROID_ATOMIC_INLINE
+int32_t android_atomic_add(int32_t increment, volatile int32_t *ptr)
+{
+    int32_t prev, status;
+    android_memory_barrier();
+    do {
+        __asm__ __volatile__ (
+        "    ll    %[prev], (%[ptr])\n"
+        "    addu  %[status], %[prev], %[inc]\n"
+        "    sc    %[status], (%[ptr])\n"
+        :  [status] "=&r" (status), [prev] "=&r" (prev)
+        :  [ptr] "r" (ptr), [inc] "Ir" (increment)
+        );
+    } while (__builtin_expect(status == 0, 0));
+    return prev;
+}
+
+extern ANDROID_ATOMIC_INLINE int32_t
+android_atomic_inc(volatile int32_t *addr)
+{
+    return android_atomic_add(1, addr);
+}
+
+extern ANDROID_ATOMIC_INLINE int32_t
+android_atomic_dec(volatile int32_t *addr)
+{
+    return android_atomic_add(-1, addr);
+}
+
+extern ANDROID_ATOMIC_INLINE int32_t
+android_atomic_and(int32_t value, volatile int32_t *ptr)
+{
+    int32_t prev, status;
+    android_memory_barrier();
+    do {
+        __asm__ __volatile__ (
+        "    ll    %[prev], (%[ptr])\n"
+        "    and   %[status], %[prev], %[value]\n"
+        "    sc    %[status], (%[ptr])\n"
+        : [prev] "=&r" (prev), [status] "=&r" (status)
+        : [ptr] "r" (ptr), [value] "Ir" (value)
+            );
+    } while (__builtin_expect(status == 0, 0));
+    return prev;
+}
+
+extern ANDROID_ATOMIC_INLINE int32_t
+android_atomic_or(int32_t value, volatile int32_t *ptr)
+{
+    int32_t prev, status;
+    android_memory_barrier();
+    do {
+        __asm__ __volatile__ (
+        "    ll    %[prev], (%[ptr])\n"
+        "    or    %[status], %[prev], %[value]\n"
+        "    sc    %[status], (%[ptr])\n"
+        : [prev] "=&r" (prev), [status] "=&r" (status)
+        : [ptr] "r" (ptr), [value] "Ir" (value)
+            );
+    } while (__builtin_expect(status == 0, 0));
+    return prev;
+}
+
+#endif /* ANDROID_CUTILS_ATOMIC_MIPS_H */
diff --git a/package/utils/adbd/src/include/cutils/atomic-x86.h b/package/utils/adbd/src/include/cutils/atomic-x86.h
new file mode 100644
index 0000000..9480f57
--- /dev/null
+++ b/package/utils/adbd/src/include/cutils/atomic-x86.h
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2010 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 ANDROID_CUTILS_ATOMIC_X86_H
+#define ANDROID_CUTILS_ATOMIC_X86_H
+
+#include <stdint.h>
+
+#ifndef ANDROID_ATOMIC_INLINE
+#define ANDROID_ATOMIC_INLINE inline __attribute__((always_inline))
+#endif
+
+extern ANDROID_ATOMIC_INLINE void android_compiler_barrier(void)
+{
+    __asm__ __volatile__ ("" : : : "memory");
+}
+
+#if ANDROID_SMP == 0
+extern ANDROID_ATOMIC_INLINE void android_memory_barrier(void)
+{
+    android_compiler_barrier();
+}
+extern ANDROID_ATOMIC_INLINE void android_memory_store_barrier(void)
+{
+    android_compiler_barrier();
+}
+#else
+extern ANDROID_ATOMIC_INLINE void android_memory_barrier(void)
+{
+    __asm__ __volatile__ ("mfence" : : : "memory");
+}
+extern ANDROID_ATOMIC_INLINE void android_memory_store_barrier(void)
+{
+    android_compiler_barrier();
+}
+#endif
+
+extern ANDROID_ATOMIC_INLINE int32_t
+android_atomic_acquire_load(volatile const int32_t *ptr)
+{
+    int32_t value = *ptr;
+    android_compiler_barrier();
+    return value;
+}
+
+extern ANDROID_ATOMIC_INLINE int32_t
+android_atomic_release_load(volatile const int32_t *ptr)
+{
+    android_memory_barrier();
+    return *ptr;
+}
+
+extern ANDROID_ATOMIC_INLINE void
+android_atomic_acquire_store(int32_t value, volatile int32_t *ptr)
+{
+    *ptr = value;
+    android_memory_barrier();
+}
+
+extern ANDROID_ATOMIC_INLINE void
+android_atomic_release_store(int32_t value, volatile int32_t *ptr)
+{
+    android_compiler_barrier();
+    *ptr = value;
+}
+
+extern ANDROID_ATOMIC_INLINE int
+android_atomic_cas(int32_t old_value, int32_t new_value, volatile int32_t *ptr)
+{
+    int32_t prev;
+    __asm__ __volatile__ ("lock; cmpxchgl %1, %2"
+                          : "=a" (prev)
+                          : "q" (new_value), "m" (*ptr), "0" (old_value)
+                          : "memory");
+    return prev != old_value;
+}
+
+extern ANDROID_ATOMIC_INLINE int
+android_atomic_acquire_cas(int32_t old_value,
+                           int32_t new_value,
+                           volatile int32_t *ptr)
+{
+    /* Loads are not reordered with other loads. */
+    return android_atomic_cas(old_value, new_value, ptr);
+}
+
+extern ANDROID_ATOMIC_INLINE int
+android_atomic_release_cas(int32_t old_value,
+                           int32_t new_value,
+                           volatile int32_t *ptr)
+{
+    /* Stores are not reordered with other stores. */
+    return android_atomic_cas(old_value, new_value, ptr);
+}
+
+extern ANDROID_ATOMIC_INLINE int32_t
+android_atomic_add(int32_t increment, volatile int32_t *ptr)
+{
+    __asm__ __volatile__ ("lock; xaddl %0, %1"
+                          : "+r" (increment), "+m" (*ptr)
+                          : : "memory");
+    /* increment now holds the old value of *ptr */
+    return increment;
+}
+
+extern ANDROID_ATOMIC_INLINE int32_t
+android_atomic_inc(volatile int32_t *addr)
+{
+    return android_atomic_add(1, addr);
+}
+
+extern ANDROID_ATOMIC_INLINE int32_t
+android_atomic_dec(volatile int32_t *addr)
+{
+    return android_atomic_add(-1, addr);
+}
+
+extern ANDROID_ATOMIC_INLINE int32_t
+android_atomic_and(int32_t value, volatile int32_t *ptr)
+{
+    int32_t prev, status;
+    do {
+        prev = *ptr;
+        status = android_atomic_cas(prev, prev & value, ptr);
+    } while (__builtin_expect(status != 0, 0));
+    return prev;
+}
+
+extern ANDROID_ATOMIC_INLINE int32_t
+android_atomic_or(int32_t value, volatile int32_t *ptr)
+{
+    int32_t prev, status;
+    do {
+        prev = *ptr;
+        status = android_atomic_cas(prev, prev | value, ptr);
+    } while (__builtin_expect(status != 0, 0));
+    return prev;
+}
+
+#endif /* ANDROID_CUTILS_ATOMIC_X86_H */
diff --git a/package/utils/adbd/src/include/cutils/atomic-x86_64.h b/package/utils/adbd/src/include/cutils/atomic-x86_64.h
new file mode 100644
index 0000000..5b5c203
--- /dev/null
+++ b/package/utils/adbd/src/include/cutils/atomic-x86_64.h
@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef ANDROID_CUTILS_ATOMIC_X86_64_H
+#define ANDROID_CUTILS_ATOMIC_X86_64_H
+
+#include <stdint.h>
+
+#ifndef ANDROID_ATOMIC_INLINE
+#define ANDROID_ATOMIC_INLINE inline __attribute__((always_inline))
+#endif
+
+extern ANDROID_ATOMIC_INLINE
+void android_compiler_barrier(void)
+{
+    __asm__ __volatile__ ("" : : : "memory");
+}
+
+#if ANDROID_SMP == 0
+extern ANDROID_ATOMIC_INLINE
+void android_memory_barrier(void)
+{
+    android_compiler_barrier();
+}
+extern ANDROID_ATOMIC_INLINE
+void android_memory_store_barrier(void)
+{
+    android_compiler_barrier();
+}
+#else
+extern ANDROID_ATOMIC_INLINE
+void android_memory_barrier(void)
+{
+    __asm__ __volatile__ ("mfence" : : : "memory");
+}
+extern ANDROID_ATOMIC_INLINE
+void android_memory_store_barrier(void)
+{
+    android_compiler_barrier();
+}
+#endif
+
+extern ANDROID_ATOMIC_INLINE
+int32_t android_atomic_acquire_load(volatile const int32_t *ptr)
+{
+    int32_t value = *ptr;
+    android_compiler_barrier();
+    return value;
+}
+
+extern ANDROID_ATOMIC_INLINE
+int64_t android_atomic_acquire_load64(volatile const int64_t *ptr)
+{
+    int64_t value = *ptr;
+    android_compiler_barrier();
+    return value;
+}
+
+extern ANDROID_ATOMIC_INLINE
+int32_t android_atomic_release_load(volatile const int32_t *ptr)
+{
+    android_memory_barrier();
+    return *ptr;
+}
+
+extern ANDROID_ATOMIC_INLINE
+int64_t android_atomic_release_load64(volatile const int64_t *ptr)
+{
+    android_memory_barrier();
+    return *ptr;
+}
+
+extern ANDROID_ATOMIC_INLINE
+void android_atomic_acquire_store(int32_t value, volatile int32_t *ptr)
+{
+    *ptr = value;
+    android_memory_barrier();
+}
+
+extern ANDROID_ATOMIC_INLINE
+void android_atomic_acquire_store64(int64_t value, volatile int64_t *ptr)
+{
+    *ptr = value;
+    android_memory_barrier();
+}
+
+extern ANDROID_ATOMIC_INLINE
+void android_atomic_release_store(int32_t value, volatile int32_t *ptr)
+{
+    android_compiler_barrier();
+    *ptr = value;
+}
+
+extern ANDROID_ATOMIC_INLINE
+void android_atomic_release_store64(int64_t value, volatile int64_t *ptr)
+{
+    android_compiler_barrier();
+    *ptr = value;
+}
+
+extern ANDROID_ATOMIC_INLINE
+int android_atomic_cas(int32_t old_value, int32_t new_value,
+                       volatile int32_t *ptr)
+{
+    int32_t prev;
+    __asm__ __volatile__ ("lock; cmpxchgl %1, %2"
+                          : "=a" (prev)
+                          : "q" (new_value), "m" (*ptr), "0" (old_value)
+                          : "memory");
+    return prev != old_value;
+}
+
+extern ANDROID_ATOMIC_INLINE
+int64_t android_atomic_cas64(int64_t old_value, int64_t new_value,
+                             volatile int64_t *ptr)
+{
+    int64_t prev;
+    __asm__ __volatile__ ("lock; cmpxchgq %1, %2"
+                          : "=a" (prev)
+                          : "q" (new_value), "m" (*ptr), "0" (old_value)
+                          : "memory");
+    return prev != old_value;
+}
+
+extern ANDROID_ATOMIC_INLINE
+int android_atomic_acquire_cas(int32_t old_value, int32_t new_value,
+                               volatile int32_t *ptr)
+{
+    /* Loads are not reordered with other loads. */
+    return android_atomic_cas(old_value, new_value, ptr);
+}
+
+extern ANDROID_ATOMIC_INLINE
+int64_t android_atomic_acquire_cas64(int64_t old_value, int64_t new_value,
+                                     volatile int64_t *ptr)
+{
+    /* Loads are not reordered with other loads. */
+    return android_atomic_cas64(old_value, new_value, ptr);
+}
+
+extern ANDROID_ATOMIC_INLINE
+int android_atomic_release_cas(int32_t old_value, int32_t new_value,
+                               volatile int32_t *ptr)
+{
+    /* Stores are not reordered with other stores. */
+    return android_atomic_cas(old_value, new_value, ptr);
+}
+
+extern ANDROID_ATOMIC_INLINE
+int64_t android_atomic_release_cas64(int64_t old_value, int64_t new_value,
+                                     volatile int64_t *ptr)
+{
+    /* Stores are not reordered with other stores. */
+    return android_atomic_cas64(old_value, new_value, ptr);
+}
+
+extern ANDROID_ATOMIC_INLINE
+int32_t android_atomic_add(int32_t increment, volatile int32_t *ptr)
+{
+    __asm__ __volatile__ ("lock; xaddl %0, %1"
+                          : "+r" (increment), "+m" (*ptr)
+                          : : "memory");
+    /* increment now holds the old value of *ptr */
+    return increment;
+}
+
+extern ANDROID_ATOMIC_INLINE
+int32_t android_atomic_inc(volatile int32_t *addr)
+{
+    return android_atomic_add(1, addr);
+}
+
+extern ANDROID_ATOMIC_INLINE
+int32_t android_atomic_dec(volatile int32_t *addr)
+{
+    return android_atomic_add(-1, addr);
+}
+
+extern ANDROID_ATOMIC_INLINE
+int32_t android_atomic_and(int32_t value, volatile int32_t *ptr)
+{
+    int32_t prev, status;
+    do {
+        prev = *ptr;
+        status = android_atomic_cas(prev, prev & value, ptr);
+    } while (__builtin_expect(status != 0, 0));
+    return prev;
+}
+
+extern ANDROID_ATOMIC_INLINE
+int32_t android_atomic_or(int32_t value, volatile int32_t *ptr)
+{
+    int32_t prev, status;
+    do {
+        prev = *ptr;
+        status = android_atomic_cas(prev, prev | value, ptr);
+    } while (__builtin_expect(status != 0, 0));
+    return prev;
+}
+
+#endif /* ANDROID_CUTILS_ATOMIC_X86_64_H */
diff --git a/package/utils/adbd/src/include/cutils/atomic.h b/package/utils/adbd/src/include/cutils/atomic.h
new file mode 100644
index 0000000..1787e34
--- /dev/null
+++ b/package/utils/adbd/src/include/cutils/atomic.h
@@ -0,0 +1,138 @@
+/*
+ * 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 ANDROID_CUTILS_ATOMIC_H
+#define ANDROID_CUTILS_ATOMIC_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * A handful of basic atomic operations.  The appropriate pthread
+ * functions should be used instead of these whenever possible.
+ *
+ * The "acquire" and "release" terms can be defined intuitively in terms
+ * of the placement of memory barriers in a simple lock implementation:
+ *   - wait until compare-and-swap(lock-is-free --> lock-is-held) succeeds
+ *   - barrier
+ *   - [do work]
+ *   - barrier
+ *   - store(lock-is-free)
+ * In very crude terms, the initial (acquire) barrier prevents any of the
+ * "work" from happening before the lock is held, and the later (release)
+ * barrier ensures that all of the work happens before the lock is released.
+ * (Think of cached writes, cache read-ahead, and instruction reordering
+ * around the CAS and store instructions.)
+ *
+ * The barriers must apply to both the compiler and the CPU.  Note it is
+ * legal for instructions that occur before an "acquire" barrier to be
+ * moved down below it, and for instructions that occur after a "release"
+ * barrier to be moved up above it.
+ *
+ * The ARM-driven implementation we use here is short on subtlety,
+ * and actually requests a full barrier from the compiler and the CPU.
+ * The only difference between acquire and release is in whether they
+ * are issued before or after the atomic operation with which they
+ * are associated.  To ease the transition to C/C++ atomic intrinsics,
+ * you should not rely on this, and instead assume that only the minimal
+ * acquire/release protection is provided.
+ *
+ * NOTE: all int32_t* values are expected to be aligned on 32-bit boundaries.
+ * If they are not, atomicity is not guaranteed.
+ */
+
+/*
+ * Basic arithmetic and bitwise operations.  These all provide a
+ * barrier with "release" ordering, and return the previous value.
+ *
+ * These have the same characteristics (e.g. what happens on overflow)
+ * as the equivalent non-atomic C operations.
+ */
+int32_t android_atomic_inc(volatile int32_t* addr);
+int32_t android_atomic_dec(volatile int32_t* addr);
+int32_t android_atomic_add(int32_t value, volatile int32_t* addr);
+int32_t android_atomic_and(int32_t value, volatile int32_t* addr);
+int32_t android_atomic_or(int32_t value, volatile int32_t* addr);
+
+/*
+ * Perform an atomic load with "acquire" or "release" ordering.
+ *
+ * This is only necessary if you need the memory barrier.  A 32-bit read
+ * from a 32-bit aligned address is atomic on all supported platforms.
+ */
+int32_t android_atomic_acquire_load(volatile const int32_t* addr);
+int32_t android_atomic_release_load(volatile const int32_t* addr);
+
+#if defined (__LP64__)
+int64_t android_atomic_acquire_load64(volatile const int64_t* addr);
+int64_t android_atomic_release_load64(volatile const int64_t* addr);
+#endif
+
+/*
+ * Perform an atomic store with "acquire" or "release" ordering.
+ *
+ * This is only necessary if you need the memory barrier.  A 32-bit write
+ * to a 32-bit aligned address is atomic on all supported platforms.
+ */
+void android_atomic_acquire_store(int32_t value, volatile int32_t* addr);
+void android_atomic_release_store(int32_t value, volatile int32_t* addr);
+
+#if defined (__LP64__)
+void android_atomic_acquire_store64(int64_t value, volatile int64_t* addr);
+void android_atomic_release_store64(int64_t value, volatile int64_t* addr);
+#endif
+
+/*
+ * Compare-and-set operation with "acquire" or "release" ordering.
+ *
+ * This returns zero if the new value was successfully stored, which will
+ * only happen when *addr == oldvalue.
+ *
+ * (The return value is inverted from implementations on other platforms,
+ * but matches the ARM ldrex/strex result.)
+ *
+ * Implementations that use the release CAS in a loop may be less efficient
+ * than possible, because we re-issue the memory barrier on each iteration.
+ */
+int android_atomic_acquire_cas(int32_t oldvalue, int32_t newvalue,
+        volatile int32_t* addr);
+int android_atomic_release_cas(int32_t oldvalue, int32_t newvalue,
+        volatile int32_t* addr);
+
+#if defined (__LP64__)
+int64_t android_atomic_acquire_cas64(int64_t old_value, int64_t new_value,
+        volatile int64_t *ptr);
+int64_t android_atomic_release_cas64(int64_t old_value, int64_t new_value,
+        volatile int64_t *ptr);
+#endif
+
+/*
+ * Aliases for code using an older version of this header.  These are now
+ * deprecated and should not be used.  The definitions will be removed
+ * in a future release.
+ */
+#define android_atomic_write android_atomic_release_store
+#define android_atomic_cmpxchg android_atomic_release_cas
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // ANDROID_CUTILS_ATOMIC_H
diff --git a/package/utils/adbd/src/include/cutils/bitops.h b/package/utils/adbd/src/include/cutils/bitops.h
new file mode 100644
index 0000000..83f671c
--- /dev/null
+++ b/package/utils/adbd/src/include/cutils/bitops.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2011 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 __CUTILS_BITOPS_H
+#define __CUTILS_BITOPS_H
+
+#include <stdbool.h>
+#include <string.h>
+#include <strings.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Bitmask Operations
+ *
+ * Note this doesn't provide any locking/exclusion, and isn't atomic.
+ * Additionally no bounds checking is done on the bitmask array.
+ *
+ * Example:
+ *
+ * int num_resources;
+ * unsigned int resource_bits[BITS_TO_WORDS(num_resources)];
+ * bitmask_init(resource_bits, num_resources);
+ * ...
+ * int bit = bitmask_ffz(resource_bits, num_resources);
+ * bitmask_set(resource_bits, bit);
+ * ...
+ * if (bitmask_test(resource_bits, bit)) { ... }
+ * ...
+ * bitmask_clear(resource_bits, bit);
+ *
+ */
+
+#define BITS_PER_WORD    (sizeof(unsigned int) * 8)
+#define BITS_TO_WORDS(x) (((x) + BITS_PER_WORD - 1) / BITS_PER_WORD)
+#define BIT_IN_WORD(x)   ((x) % BITS_PER_WORD)
+#define BIT_WORD(x)      ((x) / BITS_PER_WORD)
+#define BIT_MASK(x)      (1 << BIT_IN_WORD(x))
+
+static inline void bitmask_init(unsigned int *bitmask, int num_bits)
+{
+    memset(bitmask, 0, BITS_TO_WORDS(num_bits)*sizeof(unsigned int));
+}
+
+static inline int bitmask_ffz(unsigned int *bitmask, int num_bits)
+{
+    int bit, result;
+    size_t i;
+
+    for (i = 0; i < BITS_TO_WORDS(num_bits); i++) {
+        bit = ffs(~bitmask[i]);
+        if (bit) {
+            // ffs is 1-indexed, return 0-indexed result
+            bit--;
+            result = BITS_PER_WORD * i + bit;
+            if (result >= num_bits)
+                return -1;
+            return result;
+        }
+    }
+    return -1;
+}
+
+static inline int bitmask_weight(unsigned int *bitmask, int num_bits)
+{
+    size_t i;
+    int weight = 0;
+
+    for (i = 0; i < BITS_TO_WORDS(num_bits); i++)
+        weight += __builtin_popcount(bitmask[i]);
+    return weight;
+}
+
+static inline void bitmask_set(unsigned int *bitmask, int bit)
+{
+    bitmask[BIT_WORD(bit)] |= BIT_MASK(bit);
+}
+
+static inline void bitmask_clear(unsigned int *bitmask, int bit)
+{
+    bitmask[BIT_WORD(bit)] &= ~BIT_MASK(bit);
+}
+
+static inline bool bitmask_test(unsigned int *bitmask, int bit)
+{
+    return bitmask[BIT_WORD(bit)] & BIT_MASK(bit);
+}
+
+static inline int popcount(unsigned int x)
+{
+    return __builtin_popcount(x);
+}
+
+static inline int popcountl(unsigned long x)
+{
+    return __builtin_popcountl(x);
+}
+
+static inline int popcountll(unsigned long long x)
+{
+    return __builtin_popcountll(x);
+}
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __CUTILS_BITOPS_H */
diff --git a/package/utils/adbd/src/include/cutils/compiler.h b/package/utils/adbd/src/include/cutils/compiler.h
new file mode 100644
index 0000000..70f884a
--- /dev/null
+++ b/package/utils/adbd/src/include/cutils/compiler.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2009 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 ANDROID_CUTILS_COMPILER_H
+#define ANDROID_CUTILS_COMPILER_H
+
+/*
+ * helps the compiler's optimizer predicting branches
+ */
+
+#ifdef __cplusplus
+#   define CC_LIKELY( exp )    (__builtin_expect( !!(exp), true ))
+#   define CC_UNLIKELY( exp )  (__builtin_expect( !!(exp), false ))
+#else
+#   define CC_LIKELY( exp )    (__builtin_expect( !!(exp), 1 ))
+#   define CC_UNLIKELY( exp )  (__builtin_expect( !!(exp), 0 ))
+#endif
+
+/**
+ * exports marked symbols
+ *
+ * if used on a C++ class declaration, this macro must be inserted
+ * after the "class" keyword. For instance:
+ *
+ * template <typename TYPE>
+ * class ANDROID_API Singleton { }
+ */
+
+#define ANDROID_API __attribute__((visibility("default")))
+
+#endif // ANDROID_CUTILS_COMPILER_H
diff --git a/package/utils/adbd/src/include/cutils/config_utils.h b/package/utils/adbd/src/include/cutils/config_utils.h
new file mode 100644
index 0000000..2dea6f1
--- /dev/null
+++ b/package/utils/adbd/src/include/cutils/config_utils.h
@@ -0,0 +1,64 @@
+/*
+ * 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 __CUTILS_CONFIG_UTILS_H
+#define __CUTILS_CONFIG_UTILS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+    
+typedef struct cnode cnode;
+
+
+struct cnode
+{
+    cnode *next;
+    cnode *first_child;
+    cnode *last_child;
+    const char *name;
+    const char *value;
+};
+
+/* parse a text string into a config node tree */
+void config_load(cnode *root, char *data);
+
+/* parse a file into a config node tree */
+void config_load_file(cnode *root, const char *fn);
+
+/* create a single config node */
+cnode* config_node(const char *name, const char *value);
+
+/* locate a named child of a config node */
+cnode* config_find(cnode *root, const char *name);
+
+/* look up a child by name and return the boolean value */
+int config_bool(cnode *root, const char *name, int _default);
+
+/* look up a child by name and return the string value */
+const char* config_str(cnode *root, const char *name, const char *_default);
+
+/* add a named child to a config node (or modify it if it already exists) */
+void config_set(cnode *root, const char *name, const char *value);
+
+/* free a config node tree */
+void config_free(cnode *root);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/package/utils/adbd/src/include/cutils/cpu_info.h b/package/utils/adbd/src/include/cutils/cpu_info.h
new file mode 100644
index 0000000..78c1884
--- /dev/null
+++ b/package/utils/adbd/src/include/cutils/cpu_info.h
@@ -0,0 +1,34 @@
+/*
+ * 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 __CUTILS_CPU_INFO_H
+#define __CUTILS_CPU_INFO_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* returns a string contiaining an ASCII representation of the CPU serial number, 
+** or NULL if cpu info not available.
+** The string is a static variable, so don't call free() on it.
+*/
+extern const char* get_cpu_serial_number(void);
+    
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CUTILS_CPU_INFO_H */ 
diff --git a/package/utils/adbd/src/include/cutils/debugger.h b/package/utils/adbd/src/include/cutils/debugger.h
new file mode 100644
index 0000000..ae6bfc4
--- /dev/null
+++ b/package/utils/adbd/src/include/cutils/debugger.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2012 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 __CUTILS_DEBUGGER_H
+#define __CUTILS_DEBUGGER_H
+
+#include <sys/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if __LP64__
+#define DEBUGGER_SOCKET_NAME "android:debuggerd64"
+#else
+#define DEBUGGER_SOCKET_NAME "android:debuggerd"
+#endif
+
+typedef enum {
+    // dump a crash
+    DEBUGGER_ACTION_CRASH,
+    // dump a tombstone file
+    DEBUGGER_ACTION_DUMP_TOMBSTONE,
+    // dump a backtrace only back to the socket
+    DEBUGGER_ACTION_DUMP_BACKTRACE,
+} debugger_action_t;
+
+typedef struct {
+    debugger_action_t action;
+    pid_t tid;
+    uintptr_t abort_msg_address;
+    int32_t original_si_code;
+} debugger_msg_t;
+
+/* Dumps a process backtrace, registers, and stack to a tombstone file (requires root).
+ * Stores the tombstone path in the provided buffer.
+ * Returns 0 on success, -1 on error.
+ */
+int dump_tombstone(pid_t tid, char* pathbuf, size_t pathlen);
+
+/* Dumps a process backtrace only to the specified file (requires root).
+ * Returns 0 on success, -1 on error.
+ */
+int dump_backtrace_to_file(pid_t tid, int fd);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CUTILS_DEBUGGER_H */
diff --git a/package/utils/adbd/src/include/cutils/dir_hash.h b/package/utils/adbd/src/include/cutils/dir_hash.h
new file mode 100644
index 0000000..fbb4d02
--- /dev/null
+++ b/package/utils/adbd/src/include/cutils/dir_hash.h
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+typedef enum {
+    SHA_1,
+} HashAlgorithm;
+
+int get_file_hash(HashAlgorithm algorithm, const char *path,
+                  char *output_string, size_t max_output_string);
+
+int get_recursive_hash_manifest(HashAlgorithm algorithm,
+                                const char *directory_path,
+                                char **output_string);
diff --git a/package/utils/adbd/src/include/cutils/fs.h b/package/utils/adbd/src/include/cutils/fs.h
new file mode 100644
index 0000000..70f0b92
--- /dev/null
+++ b/package/utils/adbd/src/include/cutils/fs.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2012 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 __CUTILS_FS_H
+#define __CUTILS_FS_H
+
+#include <sys/types.h>
+#include <unistd.h>
+
+/*
+ * TEMP_FAILURE_RETRY is defined by some, but not all, versions of
+ * <unistd.h>. (Alas, it is not as standard as we'd hoped!) So, if it's
+ * not already defined, then define it here.
+ */
+#ifndef TEMP_FAILURE_RETRY
+/* Used to retry syscalls that can return EINTR. */
+#define TEMP_FAILURE_RETRY(exp) ({         \
+    typeof (exp) _rc;                      \
+    do {                                   \
+        _rc = (exp);                       \
+    } while (_rc == -1 && errno == EINTR); \
+    _rc; })
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Ensure that directory exists with given mode and owners.
+ */
+extern int fs_prepare_dir(const char* path, mode_t mode, uid_t uid, gid_t gid);
+
+/*
+ * Read single plaintext integer from given file, correctly handling files
+ * partially written with fs_write_atomic_int().
+ */
+extern int fs_read_atomic_int(const char* path, int* value);
+
+/*
+ * Write single plaintext integer to given file, creating backup while
+ * in progress.
+ */
+extern int fs_write_atomic_int(const char* path, int value);
+
+/*
+ * Ensure that all directories along given path exist, creating parent
+ * directories as needed.  Validates that given path is absolute and that
+ * it contains no relative "." or ".." paths or symlinks.  Last path segment
+ * is treated as filename and ignored, unless the path ends with "/".
+ */
+extern int fs_mkdirs(const char* path, mode_t mode);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CUTILS_FS_H */
diff --git a/package/utils/adbd/src/include/cutils/hashmap.h b/package/utils/adbd/src/include/cutils/hashmap.h
new file mode 100644
index 0000000..5cb344c
--- /dev/null
+++ b/package/utils/adbd/src/include/cutils/hashmap.h
@@ -0,0 +1,150 @@
+/*
+ * 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.
+ */
+
+/**
+ * Hash map.
+ */
+
+#ifndef __HASHMAP_H
+#define __HASHMAP_H
+
+#include <stdbool.h>
+#include <stdlib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** A hash map. */
+typedef struct Hashmap Hashmap;
+
+/**
+ * Creates a new hash map. Returns NULL if memory allocation fails.
+ *
+ * @param initialCapacity number of expected entries
+ * @param hash function which hashes keys
+ * @param equals function which compares keys for equality
+ */
+Hashmap* hashmapCreate(size_t initialCapacity,
+        int (*hash)(void* key), bool (*equals)(void* keyA, void* keyB));
+
+/**
+ * Frees the hash map. Does not free the keys or values themselves.
+ */
+void hashmapFree(Hashmap* map);
+
+/**
+ * Hashes the memory pointed to by key with the given size. Useful for
+ * implementing hash functions.
+ */
+int hashmapHash(void* key, size_t keySize);
+
+/**
+ * Puts value for the given key in the map. Returns pre-existing value if
+ * any.
+ *
+ * If memory allocation fails, this function returns NULL, the map's size
+ * does not increase, and errno is set to ENOMEM.
+ */
+void* hashmapPut(Hashmap* map, void* key, void* value);
+
+/**
+ * Gets a value from the map. Returns NULL if no entry for the given key is
+ * found or if the value itself is NULL.
+ */
+void* hashmapGet(Hashmap* map, void* key);
+
+/**
+ * Returns true if the map contains an entry for the given key.
+ */
+bool hashmapContainsKey(Hashmap* map, void* key);
+
+/**
+ * Gets the value for a key. If a value is not found, this function gets a 
+ * value and creates an entry using the given callback.
+ *
+ * If memory allocation fails, the callback is not called, this function
+ * returns NULL, and errno is set to ENOMEM.
+ */
+void* hashmapMemoize(Hashmap* map, void* key, 
+        void* (*initialValue)(void* key, void* context), void* context);
+
+/**
+ * Removes an entry from the map. Returns the removed value or NULL if no
+ * entry was present.
+ */
+void* hashmapRemove(Hashmap* map, void* key);
+
+/**
+ * Gets the number of entries in this map.
+ */
+size_t hashmapSize(Hashmap* map);
+
+/**
+ * Invokes the given callback on each entry in the map. Stops iterating if
+ * the callback returns false.
+ */
+void hashmapForEach(Hashmap* map, 
+        bool (*callback)(void* key, void* value, void* context),
+        void* context);
+
+/**
+ * Concurrency support.
+ */
+
+/**
+ * Locks the hash map so only the current thread can access it.
+ */
+void hashmapLock(Hashmap* map);
+
+/**
+ * Unlocks the hash map so other threads can access it.
+ */
+void hashmapUnlock(Hashmap* map);
+
+/**
+ * Key utilities.
+ */
+
+/**
+ * Hashes int keys. 'key' is a pointer to int.
+ */
+int hashmapIntHash(void* key);
+
+/**
+ * Compares two int keys for equality.
+ */
+bool hashmapIntEquals(void* keyA, void* keyB);
+
+/**
+ * For debugging.
+ */
+
+/**
+ * Gets current capacity.
+ */
+size_t hashmapCurrentCapacity(Hashmap* map);
+
+/**
+ * Counts the number of entry collisions.
+ */
+size_t hashmapCountCollisions(Hashmap* map);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __HASHMAP_H */ 
diff --git a/package/utils/adbd/src/include/cutils/iosched_policy.h b/package/utils/adbd/src/include/cutils/iosched_policy.h
new file mode 100644
index 0000000..07c5d1f
--- /dev/null
+++ b/package/utils/adbd/src/include/cutils/iosched_policy.h
@@ -0,0 +1,38 @@
+/*
+ * 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 __CUTILS_IOSCHED_POLICY_H
+#define __CUTILS_IOSCHED_POLICY_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+    IoSchedClass_NONE,
+    IoSchedClass_RT,
+    IoSchedClass_BE,
+    IoSchedClass_IDLE,
+} IoSchedClass;
+
+extern int android_set_ioprio(int pid, IoSchedClass clazz, int ioprio);
+extern int android_get_ioprio(int pid, IoSchedClass *clazz, int *ioprio);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CUTILS_IOSCHED_POLICY_H */ 
diff --git a/package/utils/adbd/src/include/cutils/jstring.h b/package/utils/adbd/src/include/cutils/jstring.h
new file mode 100644
index 0000000..ee0018f
--- /dev/null
+++ b/package/utils/adbd/src/include/cutils/jstring.h
@@ -0,0 +1,43 @@
+/*
+ * 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 __CUTILS_STRING16_H
+#define __CUTILS_STRING16_H
+
+#include <stdint.h>
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef uint16_t char16_t;
+
+extern char * strndup16to8 (const char16_t* s, size_t n);
+extern size_t strnlen16to8 (const char16_t* s, size_t n);
+extern char * strncpy16to8 (char *dest, const char16_t*s, size_t n);
+
+extern char16_t * strdup8to16 (const char* s, size_t *out_len);
+extern size_t strlen8to16 (const char* utf8Str);
+extern char16_t * strcpy8to16 (char16_t *dest, const char*s, size_t *out_len);
+extern char16_t * strcpylen8to16 (char16_t *dest, const char*s, int length,
+    size_t *out_len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CUTILS_STRING16_H */
diff --git a/package/utils/adbd/src/include/cutils/klog.h b/package/utils/adbd/src/include/cutils/klog.h
new file mode 100644
index 0000000..920cab9
--- /dev/null
+++ b/package/utils/adbd/src/include/cutils/klog.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2010 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 _CUTILS_KLOG_H_
+#define _CUTILS_KLOG_H_
+
+#include <stdarg.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+void klog_init(void);
+int  klog_get_level(void);
+void klog_set_level(int level);
+/* TODO: void klog_close(void); - and make klog_fd users thread safe. */
+void klog_write(int level, const char *fmt, ...)
+    __attribute__ ((format(printf, 2, 3)));
+void klog_vwrite(int level, const char *fmt, va_list ap);
+
+#ifdef __cplusplus
+}
+#endif
+
+#define KLOG_ERROR_LEVEL   3
+#define KLOG_WARNING_LEVEL 4
+#define KLOG_NOTICE_LEVEL  5
+#define KLOG_INFO_LEVEL    6
+#define KLOG_DEBUG_LEVEL   7
+
+#define KLOG_ERROR(tag,x...)   klog_write(KLOG_ERROR_LEVEL, "<3>" tag ": " x)
+#define KLOG_WARNING(tag,x...) klog_write(KLOG_WARNING_LEVEL, "<4>" tag ": " x)
+#define KLOG_NOTICE(tag,x...)  klog_write(KLOG_NOTICE_LEVEL, "<5>" tag ": " x)
+#define KLOG_INFO(tag,x...)    klog_write(KLOG_INFO_LEVEL, "<6>" tag ": " x)
+#define KLOG_DEBUG(tag,x...)   klog_write(KLOG_DEBUG_LEVEL, "<7>" tag ": " x)
+
+#define KLOG_DEFAULT_LEVEL  3  /* messages <= this level are logged */
+
+#endif
diff --git a/package/utils/adbd/src/include/cutils/list.h b/package/utils/adbd/src/include/cutils/list.h
new file mode 100644
index 0000000..4ba2cfd
--- /dev/null
+++ b/package/utils/adbd/src/include/cutils/list.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2008-2013 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 _CUTILS_LIST_H_
+#define _CUTILS_LIST_H_
+
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+struct listnode
+{
+    struct listnode *next;
+    struct listnode *prev;
+};
+
+#define node_to_item(node, container, member) \
+    (container *) (((char*) (node)) - offsetof(container, member))
+
+#define list_declare(name) \
+    struct listnode name = { \
+        .next = &name, \
+        .prev = &name, \
+    }
+
+#define list_for_each(node, list) \
+    for (node = (list)->next; node != (list); node = node->next)
+
+#define list_for_each_reverse(node, list) \
+    for (node = (list)->prev; node != (list); node = node->prev)
+
+#define list_for_each_safe(node, n, list) \
+    for (node = (list)->next, n = node->next; \
+         node != (list); \
+         node = n, n = node->next)
+
+static inline void list_init(struct listnode *node)
+{
+    node->next = node;
+    node->prev = node;
+}
+
+static inline void list_add_tail(struct listnode *head, struct listnode *item)
+{
+    item->next = head;
+    item->prev = head->prev;
+    head->prev->next = item;
+    head->prev = item;
+}
+
+static inline void list_add_head(struct listnode *head, struct listnode *item)
+{
+    item->next = head->next;
+    item->prev = head;
+    head->next->prev = item;
+    head->next = item;
+}
+
+static inline void list_remove(struct listnode *item)
+{
+    item->next->prev = item->prev;
+    item->prev->next = item->next;
+}
+
+#define list_empty(list) ((list) == (list)->next)
+#define list_head(list) ((list)->next)
+#define list_tail(list) ((list)->prev)
+
+#ifdef __cplusplus
+};
+#endif /* __cplusplus */
+
+#endif
diff --git a/package/utils/adbd/src/include/cutils/log.h b/package/utils/adbd/src/include/cutils/log.h
new file mode 100644
index 0000000..0e0248e
--- /dev/null
+++ b/package/utils/adbd/src/include/cutils/log.h
@@ -0,0 +1 @@
+#include <log/log.h>
diff --git a/package/utils/adbd/src/include/cutils/memory.h b/package/utils/adbd/src/include/cutils/memory.h
new file mode 100644
index 0000000..e725cdd
--- /dev/null
+++ b/package/utils/adbd/src/include/cutils/memory.h
@@ -0,0 +1,42 @@
+/*
+ * 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 ANDROID_CUTILS_MEMORY_H
+#define ANDROID_CUTILS_MEMORY_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* size is given in bytes and must be multiple of 2 */
+void android_memset16(uint16_t* dst, uint16_t value, size_t size);
+
+/* size is given in bytes and must be multiple of 4 */
+void android_memset32(uint32_t* dst, uint32_t value, size_t size);
+
+#if !HAVE_STRLCPY
+/* Declaration of strlcpy() for platforms that don't already have it. */
+size_t strlcpy(char *dst, const char *src, size_t size);
+#endif
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // ANDROID_CUTILS_MEMORY_H
diff --git a/package/utils/adbd/src/include/cutils/misc.h b/package/utils/adbd/src/include/cutils/misc.h
new file mode 100644
index 0000000..0de505f
--- /dev/null
+++ b/package/utils/adbd/src/include/cutils/misc.h
@@ -0,0 +1,41 @@
+/*
+ * 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 __CUTILS_MISC_H
+#define __CUTILS_MISC_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+        /* Load an entire file into a malloc'd chunk of memory
+         * that is length_of_file + 1 (null terminator).  If
+         * sz is non-zero, return the size of the file via sz.
+         * Returns 0 on failure.
+         */
+extern void *load_file(const char *fn, unsigned *sz);
+
+        /* This is the range of UIDs (and GIDs) that are reserved
+         * for assigning to applications.
+         */
+#define FIRST_APPLICATION_UID 10000
+#define LAST_APPLICATION_UID 99999
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CUTILS_MISC_H */ 
diff --git a/package/utils/adbd/src/include/cutils/multiuser.h b/package/utils/adbd/src/include/cutils/multiuser.h
new file mode 100644
index 0000000..635ddb1
--- /dev/null
+++ b/package/utils/adbd/src/include/cutils/multiuser.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2012 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 __CUTILS_MULTIUSER_H
+#define __CUTILS_MULTIUSER_H
+
+#include <sys/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// NOTE: keep in sync with android.os.UserId
+
+#define MULTIUSER_APP_PER_USER_RANGE 100000
+
+typedef uid_t userid_t;
+typedef uid_t appid_t;
+
+extern userid_t multiuser_get_user_id(uid_t uid);
+extern appid_t multiuser_get_app_id(uid_t uid);
+extern uid_t multiuser_get_uid(userid_t userId, appid_t appId);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CUTILS_MULTIUSER_H */
diff --git a/package/utils/adbd/src/include/cutils/native_handle.h b/package/utils/adbd/src/include/cutils/native_handle.h
new file mode 100644
index 0000000..268c5d3
--- /dev/null
+++ b/package/utils/adbd/src/include/cutils/native_handle.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2009 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 NATIVE_HANDLE_H_
+#define NATIVE_HANDLE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct native_handle
+{
+    int version;        /* sizeof(native_handle_t) */
+    int numFds;         /* number of file-descriptors at &data[0] */
+    int numInts;        /* number of ints at &data[numFds] */
+    int data[0];        /* numFds + numInts ints */
+} native_handle_t;
+
+/*
+ * native_handle_close
+ * 
+ * closes the file descriptors contained in this native_handle_t
+ * 
+ * return 0 on success, or a negative error code on failure
+ * 
+ */
+int native_handle_close(const native_handle_t* h);
+
+
+/*
+ * native_handle_create
+ * 
+ * creates a native_handle_t and initializes it. must be destroyed with
+ * native_handle_delete().
+ * 
+ */
+native_handle_t* native_handle_create(int numFds, int numInts);
+
+/*
+ * native_handle_delete
+ * 
+ * frees a native_handle_t allocated with native_handle_create().
+ * This ONLY frees the memory allocated for the native_handle_t, but doesn't
+ * close the file descriptors; which can be achieved with native_handle_close().
+ * 
+ * return 0 on success, or a negative error code on failure
+ * 
+ */
+int native_handle_delete(native_handle_t* h);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* NATIVE_HANDLE_H_ */
diff --git a/package/utils/adbd/src/include/cutils/open_memstream.h b/package/utils/adbd/src/include/cutils/open_memstream.h
new file mode 100644
index 0000000..b7998be
--- /dev/null
+++ b/package/utils/adbd/src/include/cutils/open_memstream.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2010 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 __CUTILS_OPEN_MEMSTREAM_H__
+#define __CUTILS_OPEN_MEMSTREAM_H__
+
+#include <stdio.h>
+
+#ifndef HAVE_OPEN_MEMSTREAM
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+FILE* open_memstream(char** bufp, size_t* sizep);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*!HAVE_OPEN_MEMSTREAM*/
+
+#endif /*__CUTILS_OPEN_MEMSTREAM_H__*/
diff --git a/package/utils/adbd/src/include/cutils/partition_utils.h b/package/utils/adbd/src/include/cutils/partition_utils.h
new file mode 100644
index 0000000..49f95d5
--- /dev/null
+++ b/package/utils/adbd/src/include/cutils/partition_utils.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2011, 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 __CUTILS_PARTITION_WIPED_H__
+#define __CUTILS_PARTITION_WIPED_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+int partition_wiped(char *source);
+void erase_footer(const char *dev_path, long long size);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __CUTILS_PARTITION_WIPED_H__ */
diff --git a/package/utils/adbd/src/include/cutils/process_name.h b/package/utils/adbd/src/include/cutils/process_name.h
new file mode 100644
index 0000000..1e72e5c
--- /dev/null
+++ b/package/utils/adbd/src/include/cutils/process_name.h
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+/**
+ * Gives the current process a name.
+ */
+
+#ifndef __PROCESS_NAME_H
+#define __PROCESS_NAME_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Sets the current process name.
+ *
+ * Warning: This leaks a string every time you call it. Use judiciously!
+ */
+void set_process_name(const char* process_name);
+
+/** Gets the current process name. */
+const char* get_process_name(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __PROCESS_NAME_H */ 
diff --git a/package/utils/adbd/src/include/cutils/properties.h b/package/utils/adbd/src/include/cutils/properties.h
new file mode 100644
index 0000000..cd1ee6a
--- /dev/null
+++ b/package/utils/adbd/src/include/cutils/properties.h
@@ -0,0 +1,151 @@
+/*
+ * 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 __CUTILS_PROPERTIES_H
+#define __CUTILS_PROPERTIES_H
+
+// changed by feilv
+//#include <sys/cdefs.h>
+//#include <stddef.h>
+//#include <sys/system_properties.h>
+//#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* System properties are *small* name value pairs managed by the
+** property service.  If your data doesn't fit in the provided
+** space it is not appropriate for a system property.
+**
+** WARNING: system/bionic/include/sys/system_properties.h also defines
+**          these, but with different names.  (TODO: fix that)
+*/
+// changed by feilv
+#define PROPERTY_KEY_MAX   32
+#define PROPERTY_VALUE_MAX  96
+
+/* property_get: returns the length of the value which will never be
+** greater than PROPERTY_VALUE_MAX - 1 and will always be zero terminated.
+** (the length does not include the terminating zero).
+**
+** If the property read fails or returns an empty value, the default
+** value is used (if nonnull).
+*/
+int property_get(const char *key, char *value, const char *default_value);
+
+/* property_get_bool: returns the value of key coerced into a
+** boolean. If the property is not set, then the default value is returned.
+**
+* The following is considered to be true (1):
+**   "1", "true", "y", "yes", "on"
+**
+** The following is considered to be false (0):
+**   "0", "false", "n", "no", "off"
+**
+** The conversion is whitespace-sensitive (e.g. " off" will not be false).
+**
+** If no property with this key is set (or the key is NULL) or the boolean
+** conversion fails, the default value is returned.
+**/
+int8_t property_get_bool(const char *key, int8_t default_value);
+
+/* property_get_int64: returns the value of key truncated and coerced into a
+** int64_t. If the property is not set, then the default value is used.
+**
+** The numeric conversion is identical to strtoimax with the base inferred:
+** - All digits up to the first non-digit characters are read
+** - The longest consecutive prefix of digits is converted to a long
+**
+** Valid strings of digits are:
+** - An optional sign character + or -
+** - An optional prefix indicating the base (otherwise base 10 is assumed)
+**   -- 0 prefix is octal
+**   -- 0x / 0X prefix is hex
+**
+** Leading/trailing whitespace is ignored. Overflow/underflow will cause
+** numeric conversion to fail.
+**
+** If no property with this key is set (or the key is NULL) or the numeric
+** conversion fails, the default value is returned.
+**/
+int64_t property_get_int64(const char *key, int64_t default_value);
+
+/* property_get_int32: returns the value of key truncated and coerced into an
+** int32_t. If the property is not set, then the default value is used.
+**
+** The numeric conversion is identical to strtoimax with the base inferred:
+** - All digits up to the first non-digit characters are read
+** - The longest consecutive prefix of digits is converted to a long
+**
+** Valid strings of digits are:
+** - An optional sign character + or -
+** - An optional prefix indicating the base (otherwise base 10 is assumed)
+**   -- 0 prefix is octal
+**   -- 0x / 0X prefix is hex
+**
+** Leading/trailing whitespace is ignored. Overflow/underflow will cause
+** numeric conversion to fail.
+**
+** If no property with this key is set (or the key is NULL) or the numeric
+** conversion fails, the default value is returned.
+**/
+int32_t property_get_int32(const char *key, int32_t default_value);
+
+/* property_set: returns 0 on success, < 0 on failure
+*/
+int property_set(const char *key, const char *value);
+    
+int property_list(void (*propfn)(const char *key, const char *value, void *cookie), void *cookie);    
+
+#if defined(__BIONIC_FORTIFY)
+
+extern int __property_get_real(const char *, char *, const char *)
+    __asm__(__USER_LABEL_PREFIX__ "property_get");
+__errordecl(__property_get_too_small_error, "property_get() called with too small of a buffer");
+
+__BIONIC_FORTIFY_INLINE
+int property_get(const char *key, char *value, const char *default_value) {
+    size_t bos = __bos(value);
+    if (bos < PROPERTY_VALUE_MAX) {
+        __property_get_too_small_error();
+    }
+    return __property_get_real(key, value, default_value);
+}
+
+#endif
+
+#ifdef HAVE_SYSTEM_PROPERTY_SERVER
+/*
+ * We have an external property server instead of built-in libc support.
+ * Used by the simulator.
+ */
+#define SYSTEM_PROPERTY_PIPE_NAME       "/tmp/android-sysprop"
+
+enum {
+    kSystemPropertyUnknown = 0,
+    kSystemPropertyGet,
+    kSystemPropertySet,
+    kSystemPropertyList
+};
+#endif /*HAVE_SYSTEM_PROPERTY_SERVER*/
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/package/utils/adbd/src/include/cutils/qtaguid.h b/package/utils/adbd/src/include/cutils/qtaguid.h
new file mode 100644
index 0000000..f8550fd
--- /dev/null
+++ b/package/utils/adbd/src/include/cutils/qtaguid.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2011 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 __CUTILS_QTAGUID_H
+#define __CUTILS_QTAGUID_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Set tags (and owning UIDs) for network sockets.
+*/
+extern int qtaguid_tagSocket(int sockfd, int tag, uid_t uid);
+
+/*
+ * Untag a network socket before closing.
+*/
+extern int qtaguid_untagSocket(int sockfd);
+
+/*
+ * For the given uid, switch counter sets.
+ * The kernel only keeps a limited number of sets.
+ * 2 for now.
+ */
+extern int qtaguid_setCounterSet(int counterSetNum, uid_t uid);
+
+/*
+ * Delete all tag info that relates to the given tag an uid.
+ * If the tag is 0, then ALL info about the uid is freeded.
+ * The delete data also affects active tagged socketd, which are
+ * then untagged.
+ * The calling process can only operate on its own tags.
+ * Unless it is part of the happy AID_NET_BW_ACCT group.
+ * In which case it can clobber everything.
+ */
+extern int qtaguid_deleteTagData(int tag, uid_t uid);
+
+/*
+ * Enable/disable qtaguid functionnality at a lower level.
+ * When pacified, the kernel will accept commands but do nothing.
+ */
+extern int qtaguid_setPacifier(int on);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CUTILS_QTAG_UID_H */
diff --git a/package/utils/adbd/src/include/cutils/record_stream.h b/package/utils/adbd/src/include/cutils/record_stream.h
new file mode 100644
index 0000000..bfac87a
--- /dev/null
+++ b/package/utils/adbd/src/include/cutils/record_stream.h
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+
+/*
+ * A simple utility for reading fixed records out of a stream fd
+ */
+
+#ifndef _CUTILS_RECORD_STREAM_H
+#define _CUTILS_RECORD_STREAM_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+typedef struct RecordStream RecordStream;
+
+extern RecordStream *record_stream_new(int fd, size_t maxRecordLen);
+extern void record_stream_free(RecordStream *p_rs);
+
+extern int record_stream_get_next (RecordStream *p_rs, void ** p_outRecord, 
+                                    size_t *p_outRecordLen);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /*_CUTILS_RECORD_STREAM_H*/
+
diff --git a/package/utils/adbd/src/include/cutils/sched_policy.h b/package/utils/adbd/src/include/cutils/sched_policy.h
new file mode 100644
index 0000000..ba84ce3
--- /dev/null
+++ b/package/utils/adbd/src/include/cutils/sched_policy.h
@@ -0,0 +1,61 @@
+/*
+ * 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 __CUTILS_SCHED_POLICY_H
+#define __CUTILS_SCHED_POLICY_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Keep in sync with THREAD_GROUP_* in frameworks/base/core/java/android/os/Process.java */
+typedef enum {
+    SP_DEFAULT    = -1,
+    SP_BACKGROUND = 0,
+    SP_FOREGROUND = 1,
+    SP_SYSTEM     = 2,  // can't be used with set_sched_policy()
+    SP_AUDIO_APP  = 3,
+    SP_AUDIO_SYS  = 4,
+    SP_CNT,
+    SP_MAX        = SP_CNT - 1,
+    SP_SYSTEM_DEFAULT = SP_FOREGROUND,
+} SchedPolicy;
+
+/* Assign thread tid to the cgroup associated with the specified policy.
+ * If the thread is a thread group leader, that is it's gettid() == getpid(),
+ * then the other threads in the same thread group are _not_ affected.
+ * On platforms which support gettid(), zero tid means current thread.
+ * Return value: 0 for success, or -errno for error.
+ */
+extern int set_sched_policy(int tid, SchedPolicy policy);
+
+/* Return the policy associated with the cgroup of thread tid via policy pointer.
+ * On platforms which support gettid(), zero tid means current thread.
+ * Return value: 0 for success, or -1 for error and set errno.
+ */
+extern int get_sched_policy(int tid, SchedPolicy *policy);
+
+/* Return a displayable string corresponding to policy.
+ * Return value: non-NULL NUL-terminated name of unspecified length;
+ * the caller is responsible for displaying the useful part of the string.
+ */
+extern const char *get_sched_policy_name(SchedPolicy policy);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CUTILS_SCHED_POLICY_H */ 
diff --git a/package/utils/adbd/src/include/cutils/sockets.h b/package/utils/adbd/src/include/cutils/sockets.h
new file mode 100644
index 0000000..daf43ec
--- /dev/null
+++ b/package/utils/adbd/src/include/cutils/sockets.h
@@ -0,0 +1,114 @@
+/*
+ * 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 __CUTILS_SOCKETS_H
+#define __CUTILS_SOCKETS_H
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+
+#ifdef HAVE_WINSOCK
+#include <winsock2.h>
+typedef int  socklen_t;
+#elif HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+
+#define ANDROID_SOCKET_ENV_PREFIX	"ANDROID_SOCKET_"
+#define ANDROID_SOCKET_DIR		"/dev/socket"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * android_get_control_socket - simple helper function to get the file
+ * descriptor of our init-managed Unix domain socket. `name' is the name of the
+ * socket, as given in init.rc. Returns -1 on error.
+ *
+ * This is inline and not in libcutils proper because we want to use this in
+ * third-party daemons with minimal modification.
+ */
+static inline int android_get_control_socket(const char *name)
+{
+	char key[64] = ANDROID_SOCKET_ENV_PREFIX;
+	const char *val;
+	int fd;
+
+	/* build our environment variable, counting cycles like a wolf ... */
+#if HAVE_STRLCPY
+	strlcpy(key + sizeof(ANDROID_SOCKET_ENV_PREFIX) - 1,
+		name,
+		sizeof(key) - sizeof(ANDROID_SOCKET_ENV_PREFIX));
+#else	/* for the host, which may lack the almightly strncpy ... */
+	strncpy(key + sizeof(ANDROID_SOCKET_ENV_PREFIX) - 1,
+		name,
+		sizeof(key) - sizeof(ANDROID_SOCKET_ENV_PREFIX));
+	key[sizeof(key)-1] = '\0';
+#endif
+
+	val = getenv(key);
+	if (!val)
+		return -1;
+
+	errno = 0;
+	fd = strtol(val, NULL, 10);
+	if (errno)
+		return -1;
+
+	return fd;
+}
+
+/*
+ * See also android.os.LocalSocketAddress.Namespace
+ */
+// Linux "abstract" (non-filesystem) namespace
+#define ANDROID_SOCKET_NAMESPACE_ABSTRACT 0
+// Android "reserved" (/dev/socket) namespace
+#define ANDROID_SOCKET_NAMESPACE_RESERVED 1
+// Normal filesystem namespace
+#define ANDROID_SOCKET_NAMESPACE_FILESYSTEM 2
+
+extern int socket_loopback_client(int port, int type);
+extern int socket_network_client(const char *host, int port, int type);
+extern int socket_network_client_timeout(const char *host, int port, int type,
+                                         int timeout);
+extern int socket_loopback_server(int port, int type);
+extern int socket_local_server(const char *name, int namespaceId, int type);
+extern int socket_local_server_bind(int s, const char *name, int namespaceId);
+extern int socket_local_client_connect(int fd, 
+        const char *name, int namespaceId, int type);
+extern int socket_local_client(const char *name, int namespaceId, int type);
+extern int socket_inaddr_any_server(int port, int type);
+
+/*
+ * socket_peer_is_trusted - Takes a socket which is presumed to be a
+ * connected local socket (e.g. AF_LOCAL) and returns whether the peer
+ * (the userid that owns the process on the other end of that socket)
+ * is one of the two trusted userids, root or shell.
+ *
+ * Note: This only works as advertised on the Android OS and always
+ * just returns true when called on other operating systems.
+ */
+extern bool socket_peer_is_trusted(int fd);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CUTILS_SOCKETS_H */ 
diff --git a/package/utils/adbd/src/include/cutils/str_parms.h b/package/utils/adbd/src/include/cutils/str_parms.h
new file mode 100644
index 0000000..66f3637
--- /dev/null
+++ b/package/utils/adbd/src/include/cutils/str_parms.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2011 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 __CUTILS_STR_PARMS_H
+#define __CUTILS_STR_PARMS_H
+
+#include <stdint.h>
+
+struct str_parms;
+
+struct str_parms *str_parms_create(void);
+struct str_parms *str_parms_create_str(const char *_string);
+void str_parms_destroy(struct str_parms *str_parms);
+
+void str_parms_del(struct str_parms *str_parms, const char *key);
+
+int str_parms_add_str(struct str_parms *str_parms, const char *key,
+                      const char *value);
+int str_parms_add_int(struct str_parms *str_parms, const char *key, int value);
+
+int str_parms_add_float(struct str_parms *str_parms, const char *key,
+                        float value);
+
+// Returns non-zero if the str_parms contains the specified key.
+int str_parms_has_key(struct str_parms *str_parms, const char *key);
+
+// Gets value associated with the specified key (if present), placing it in the buffer
+// pointed to by the out_val parameter.  Returns the length of the returned string value.
+// If 'key' isn't in the parms, then return -ENOENT (-2) and leave 'out_val' untouched.
+int str_parms_get_str(struct str_parms *str_parms, const char *key,
+                      char *out_val, int len);
+int str_parms_get_int(struct str_parms *str_parms, const char *key,
+                      int *out_val);
+int str_parms_get_float(struct str_parms *str_parms, const char *key,
+                        float *out_val);
+
+char *str_parms_to_str(struct str_parms *str_parms);
+
+/* debug */
+void str_parms_dump(struct str_parms *str_parms);
+
+#endif /* __CUTILS_STR_PARMS_H */
diff --git a/package/utils/adbd/src/include/cutils/threads.h b/package/utils/adbd/src/include/cutils/threads.h
new file mode 100644
index 0000000..acf8f48
--- /dev/null
+++ b/package/utils/adbd/src/include/cutils/threads.h
@@ -0,0 +1,146 @@
+/*
+ * 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 _LIBS_CUTILS_THREADS_H
+#define _LIBS_CUTILS_THREADS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/***********************************************************************/
+/***********************************************************************/
+/*****                                                             *****/
+/*****         local thread storage                                *****/
+/*****                                                             *****/
+/***********************************************************************/
+/***********************************************************************/
+
+#ifdef HAVE_PTHREADS
+
+#include  <pthread.h>
+
+typedef struct {
+    pthread_mutex_t   lock;
+    int               has_tls;
+    pthread_key_t     tls;
+
+} thread_store_t;
+
+#define  THREAD_STORE_INITIALIZER  { PTHREAD_MUTEX_INITIALIZER, 0, 0 }
+
+#elif defined HAVE_WIN32_THREADS
+
+#include <windows.h>
+
+typedef struct {
+    int               lock_init;
+    int               has_tls;
+    DWORD             tls;
+    CRITICAL_SECTION  lock;
+
+} thread_store_t;
+
+#define  THREAD_STORE_INITIALIZER  { 0, 0, 0, {0, 0, 0, 0, 0, 0} }
+
+#else
+#  error  "no thread_store_t implementation for your platform !!"
+#endif
+
+typedef void  (*thread_store_destruct_t)(void*  value);
+
+extern void*  thread_store_get(thread_store_t*  store);
+
+extern void   thread_store_set(thread_store_t*          store, 
+                               void*                    value,
+                               thread_store_destruct_t  destroy);
+
+/***********************************************************************/
+/***********************************************************************/
+/*****                                                             *****/
+/*****         mutexes                                             *****/
+/*****                                                             *****/
+/***********************************************************************/
+/***********************************************************************/
+
+#ifdef HAVE_PTHREADS
+
+typedef pthread_mutex_t   mutex_t;
+
+#define  MUTEX_INITIALIZER  PTHREAD_MUTEX_INITIALIZER
+
+static __inline__ void  mutex_lock(mutex_t*  lock)
+{
+    pthread_mutex_lock(lock);
+}
+static __inline__ void  mutex_unlock(mutex_t*  lock)
+{
+    pthread_mutex_unlock(lock);
+}
+static __inline__ int  mutex_init(mutex_t*  lock)
+{
+    return pthread_mutex_init(lock, NULL);
+}
+static __inline__ void mutex_destroy(mutex_t*  lock)
+{
+    pthread_mutex_destroy(lock);
+}
+#endif
+
+#ifdef HAVE_WIN32_THREADS
+typedef struct { 
+    int                init;
+    CRITICAL_SECTION   lock[1];
+} mutex_t;
+
+#define  MUTEX_INITIALIZER  { 0, {{ NULL, 0, 0, NULL, NULL, 0 }} }
+
+static __inline__ void  mutex_lock(mutex_t*  lock)
+{
+    if (!lock->init) {
+        lock->init = 1;
+        InitializeCriticalSection( lock->lock );
+        lock->init = 2;
+    } else while (lock->init != 2)
+        Sleep(10);
+
+    EnterCriticalSection(lock->lock);
+}
+
+static __inline__ void  mutex_unlock(mutex_t*  lock)
+{
+    LeaveCriticalSection(lock->lock);
+}
+static __inline__ int  mutex_init(mutex_t*  lock)
+{
+    InitializeCriticalSection(lock->lock);
+    lock->init = 2;
+    return 0;
+}
+static __inline__ void  mutex_destroy(mutex_t*  lock)
+{
+    if (lock->init) {
+        lock->init = 0;
+        DeleteCriticalSection(lock->lock); 
+    }
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LIBS_CUTILS_THREADS_H */
diff --git a/package/utils/adbd/src/include/cutils/trace.h b/package/utils/adbd/src/include/cutils/trace.h
new file mode 100644
index 0000000..2f3cc40
--- /dev/null
+++ b/package/utils/adbd/src/include/cutils/trace.h
@@ -0,0 +1,298 @@
+/*
+ * Copyright (C) 2012 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 _LIBS_CUTILS_TRACE_H
+#define _LIBS_CUTILS_TRACE_H
+
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <cutils/compiler.h>
+#ifdef ANDROID_SMP
+#include <cutils/atomic-inline.h>
+#else
+#include <cutils/atomic.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/**
+ * The ATRACE_TAG macro can be defined before including this header to trace
+ * using one of the tags defined below.  It must be defined to one of the
+ * following ATRACE_TAG_* macros.  The trace tag is used to filter tracing in
+ * userland to avoid some of the runtime cost of tracing when it is not desired.
+ *
+ * Defining ATRACE_TAG to be ATRACE_TAG_ALWAYS will result in the tracing always
+ * being enabled - this should ONLY be done for debug code, as userland tracing
+ * has a performance cost even when the trace is not being recorded.  Defining
+ * ATRACE_TAG to be ATRACE_TAG_NEVER or leaving ATRACE_TAG undefined will result
+ * in the tracing always being disabled.
+ *
+ * ATRACE_TAG_HAL should be bitwise ORed with the relevant tags for tracing
+ * within a hardware module.  For example a camera hardware module would set:
+ * #define ATRACE_TAG  (ATRACE_TAG_CAMERA | ATRACE_TAG_HAL)
+ *
+ * Keep these in sync with frameworks/base/core/java/android/os/Trace.java.
+ */
+#define ATRACE_TAG_NEVER            0       // This tag is never enabled.
+#define ATRACE_TAG_ALWAYS           (1<<0)  // This tag is always enabled.
+#define ATRACE_TAG_GRAPHICS         (1<<1)
+#define ATRACE_TAG_INPUT            (1<<2)
+#define ATRACE_TAG_VIEW             (1<<3)
+#define ATRACE_TAG_WEBVIEW          (1<<4)
+#define ATRACE_TAG_WINDOW_MANAGER   (1<<5)
+#define ATRACE_TAG_ACTIVITY_MANAGER (1<<6)
+#define ATRACE_TAG_SYNC_MANAGER     (1<<7)
+#define ATRACE_TAG_AUDIO            (1<<8)
+#define ATRACE_TAG_VIDEO            (1<<9)
+#define ATRACE_TAG_CAMERA           (1<<10)
+#define ATRACE_TAG_HAL              (1<<11)
+#define ATRACE_TAG_APP              (1<<12)
+#define ATRACE_TAG_RESOURCES        (1<<13)
+#define ATRACE_TAG_DALVIK           (1<<14)
+#define ATRACE_TAG_RS               (1<<15)
+#define ATRACE_TAG_BIONIC           (1<<16)
+#define ATRACE_TAG_LAST             ATRACE_TAG_BIONIC
+
+// Reserved for initialization.
+#define ATRACE_TAG_NOT_READY        (1LL<<63)
+
+#define ATRACE_TAG_VALID_MASK ((ATRACE_TAG_LAST - 1) | ATRACE_TAG_LAST)
+
+#ifndef ATRACE_TAG
+#define ATRACE_TAG ATRACE_TAG_NEVER
+#elif ATRACE_TAG > ATRACE_TAG_VALID_MASK
+#error ATRACE_TAG must be defined to be one of the tags defined in cutils/trace.h
+#endif
+
+#ifdef HAVE_ANDROID_OS
+/**
+ * Maximum size of a message that can be logged to the trace buffer.
+ * Note this message includes a tag, the pid, and the string given as the name.
+ * Names should be kept short to get the most use of the trace buffer.
+ */
+#define ATRACE_MESSAGE_LENGTH 1024
+
+/**
+ * Opens the trace file for writing and reads the property for initial tags.
+ * The atrace.tags.enableflags property sets the tags to trace.
+ * This function should not be explicitly called, the first call to any normal
+ * trace function will cause it to be run safely.
+ */
+void atrace_setup();
+
+/**
+ * If tracing is ready, set atrace_enabled_tags to the system property
+ * debug.atrace.tags.enableflags. Can be used as a sysprop change callback.
+ */
+void atrace_update_tags();
+
+/**
+ * Set whether the process is debuggable.  By default the process is not
+ * considered debuggable.  If the process is not debuggable then application-
+ * level tracing is not allowed unless the ro.debuggable system property is
+ * set to '1'.
+ */
+void atrace_set_debuggable(bool debuggable);
+
+/**
+ * Set whether tracing is enabled for the current process.  This is used to
+ * prevent tracing within the Zygote process.
+ */
+void atrace_set_tracing_enabled(bool enabled);
+
+/**
+ * Flag indicating whether setup has been completed, initialized to 0.
+ * Nonzero indicates setup has completed.
+ * Note: This does NOT indicate whether or not setup was successful.
+ */
+extern volatile int32_t atrace_is_ready;
+
+/**
+ * Set of ATRACE_TAG flags to trace for, initialized to ATRACE_TAG_NOT_READY.
+ * A value of zero indicates setup has failed.
+ * Any other nonzero value indicates setup has succeeded, and tracing is on.
+ */
+extern uint64_t atrace_enabled_tags;
+
+/**
+ * Handle to the kernel's trace buffer, initialized to -1.
+ * Any other value indicates setup has succeeded, and is a valid fd for tracing.
+ */
+extern int atrace_marker_fd;
+
+/**
+ * atrace_init readies the process for tracing by opening the trace_marker file.
+ * Calling any trace function causes this to be run, so calling it is optional.
+ * This can be explicitly run to avoid setup delay on first trace function.
+ */
+#define ATRACE_INIT() atrace_init()
+static inline void atrace_init()
+{
+    if (CC_UNLIKELY(!android_atomic_acquire_load(&atrace_is_ready))) {
+        atrace_setup();
+    }
+}
+
+/**
+ * Get the mask of all tags currently enabled.
+ * It can be used as a guard condition around more expensive trace calculations.
+ * Every trace function calls this, which ensures atrace_init is run.
+ */
+#define ATRACE_GET_ENABLED_TAGS() atrace_get_enabled_tags()
+static inline uint64_t atrace_get_enabled_tags()
+{
+    atrace_init();
+    return atrace_enabled_tags;
+}
+
+/**
+ * Test if a given tag is currently enabled.
+ * Returns nonzero if the tag is enabled, otherwise zero.
+ * It can be used as a guard condition around more expensive trace calculations.
+ */
+#define ATRACE_ENABLED() atrace_is_tag_enabled(ATRACE_TAG)
+static inline uint64_t atrace_is_tag_enabled(uint64_t tag)
+{
+    return atrace_get_enabled_tags() & tag;
+}
+
+/**
+ * Trace the beginning of a context.  name is used to identify the context.
+ * This is often used to time function execution.
+ */
+#define ATRACE_BEGIN(name) atrace_begin(ATRACE_TAG, name)
+static inline void atrace_begin(uint64_t tag, const char* name)
+{
+    if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
+        char buf[ATRACE_MESSAGE_LENGTH];
+        size_t len;
+
+        len = snprintf(buf, ATRACE_MESSAGE_LENGTH, "B|%d|%s", getpid(), name);
+        write(atrace_marker_fd, buf, len);
+    }
+}
+
+/**
+ * Trace the end of a context.
+ * This should match up (and occur after) a corresponding ATRACE_BEGIN.
+ */
+#define ATRACE_END() atrace_end(ATRACE_TAG)
+static inline void atrace_end(uint64_t tag)
+{
+    if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
+        char c = 'E';
+        write(atrace_marker_fd, &c, 1);
+    }
+}
+
+/**
+ * Trace the beginning of an asynchronous event. Unlike ATRACE_BEGIN/ATRACE_END
+ * contexts, asynchronous events do not need to be nested. The name describes
+ * the event, and the cookie provides a unique identifier for distinguishing
+ * simultaneous events. The name and cookie used to begin an event must be
+ * used to end it.
+ */
+#define ATRACE_ASYNC_BEGIN(name, cookie) \
+    atrace_async_begin(ATRACE_TAG, name, cookie)
+static inline void atrace_async_begin(uint64_t tag, const char* name,
+        int32_t cookie)
+{
+    if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
+        char buf[ATRACE_MESSAGE_LENGTH];
+        size_t len;
+
+        len = snprintf(buf, ATRACE_MESSAGE_LENGTH, "S|%d|%s|%" PRId32,
+                getpid(), name, cookie);
+        write(atrace_marker_fd, buf, len);
+    }
+}
+
+/**
+ * Trace the end of an asynchronous event.
+ * This should have a corresponding ATRACE_ASYNC_BEGIN.
+ */
+#define ATRACE_ASYNC_END(name, cookie) atrace_async_end(ATRACE_TAG, name, cookie)
+static inline void atrace_async_end(uint64_t tag, const char* name,
+        int32_t cookie)
+{
+    if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
+        char buf[ATRACE_MESSAGE_LENGTH];
+        size_t len;
+
+        len = snprintf(buf, ATRACE_MESSAGE_LENGTH, "F|%d|%s|%" PRId32,
+                getpid(), name, cookie);
+        write(atrace_marker_fd, buf, len);
+    }
+}
+
+
+/**
+ * Traces an integer counter value.  name is used to identify the counter.
+ * This can be used to track how a value changes over time.
+ */
+#define ATRACE_INT(name, value) atrace_int(ATRACE_TAG, name, value)
+static inline void atrace_int(uint64_t tag, const char* name, int32_t value)
+{
+    if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
+        char buf[ATRACE_MESSAGE_LENGTH];
+        size_t len;
+
+        len = snprintf(buf, ATRACE_MESSAGE_LENGTH, "C|%d|%s|%" PRId32,
+                getpid(), name, value);
+        write(atrace_marker_fd, buf, len);
+    }
+}
+
+/**
+ * Traces a 64-bit integer counter value.  name is used to identify the
+ * counter. This can be used to track how a value changes over time.
+ */
+#define ATRACE_INT64(name, value) atrace_int64(ATRACE_TAG, name, value)
+static inline void atrace_int64(uint64_t tag, const char* name, int64_t value)
+{
+    if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
+        char buf[ATRACE_MESSAGE_LENGTH];
+        size_t len;
+
+        len = snprintf(buf, ATRACE_MESSAGE_LENGTH, "C|%d|%s|%" PRId64,
+                getpid(), name, value);
+        write(atrace_marker_fd, buf, len);
+    }
+}
+
+#else // not HAVE_ANDROID_OS
+
+#define ATRACE_INIT()
+#define ATRACE_GET_ENABLED_TAGS()
+#define ATRACE_ENABLED() 0
+#define ATRACE_BEGIN(name)
+#define ATRACE_END()
+#define ATRACE_ASYNC_BEGIN(name, cookie)
+#define ATRACE_ASYNC_END(name, cookie)
+#define ATRACE_INT(name, value)
+
+#endif // not HAVE_ANDROID_OS
+
+#ifdef __cplusplus
+}
+#endif
+#endif // _LIBS_CUTILS_TRACE_H
diff --git a/package/utils/adbd/src/include/cutils/tztime.h b/package/utils/adbd/src/include/cutils/tztime.h
new file mode 100644
index 0000000..dbdbd60
--- /dev/null
+++ b/package/utils/adbd/src/include/cutils/tztime.h
@@ -0,0 +1,24 @@
+/*
+ * 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 _CUTILS_TZTIME_H
+#define _CUTILS_TZTIME_H
+
+// TODO: fix both callers to just include <bionic_time.h> themselves.
+#include <bionic_time.h>
+
+#endif /* __CUTILS_TZTIME_H */ 
+
diff --git a/package/utils/adbd/src/include/cutils/uevent.h b/package/utils/adbd/src/include/cutils/uevent.h
new file mode 100644
index 0000000..4cca7e5
--- /dev/null
+++ b/package/utils/adbd/src/include/cutils/uevent.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2011 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 __CUTILS_UEVENT_H
+#define __CUTILS_UEVENT_H
+
+#include <stdbool.h>
+#include <sys/socket.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int uevent_open_socket(int buf_sz, bool passcred);
+ssize_t uevent_kernel_multicast_recv(int socket, void *buffer, size_t length);
+ssize_t uevent_kernel_multicast_uid_recv(int socket, void *buffer, size_t length, uid_t *uid);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CUTILS_UEVENT_H */
diff --git a/package/utils/adbd/src/include/diskconfig/diskconfig.h b/package/utils/adbd/src/include/diskconfig/diskconfig.h
new file mode 100644
index 0000000..d45b99e
--- /dev/null
+++ b/package/utils/adbd/src/include/diskconfig/diskconfig.h
@@ -0,0 +1,130 @@
+/* system/core/include/diskconfig/diskconfig.h
+ *
+ * Copyright 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.
+ */
+
+#ifndef __LIBS_DISKCONFIG_H
+#define __LIBS_DISKCONFIG_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MAX_NAME_LEN                 512
+#define MAX_NUM_PARTS                16
+
+/* known partition schemes */
+#define PART_SCHEME_MBR              0x1
+#define PART_SCHEME_GPT              0x2
+
+/* PC Bios partition status */
+#define PC_PART_ACTIVE               0x80
+#define PC_PART_NORMAL               0x0
+
+/* Known (rather, used by us) partition types */
+#define PC_PART_TYPE_LINUX           0x83
+#define PC_PART_TYPE_EXTENDED        0x05
+#define PC_PART_TYPE_FAT32           0x0c
+
+#define PC_NUM_BOOT_RECORD_PARTS     4
+
+#define PC_EBR_LOGICAL_PART          0
+#define PC_EBR_NEXT_PTR_PART         1
+
+#define PC_BIOS_BOOT_SIG             0xAA55
+
+#define PC_MBR_DISK_OFFSET           0
+#define PC_MBR_SIZE                  512
+
+#define PART_ACTIVE_FLAG             0x1
+
+struct chs {
+    uint8_t head;
+    uint8_t sector;
+    uint8_t cylinder;
+} __attribute__((__packed__));
+
+/* 16 byte pc partition descriptor that sits in MBR and EPBR.
+ * Note: multi-byte entities have little-endian layout on disk */
+struct pc_partition {
+    uint8_t status;     /* byte  0     */
+    struct chs start;   /* bytes 1-3   */
+    uint8_t type;       /* byte  4     */
+    struct chs end;     /* bytes 5-7   */
+    uint32_t start_lba; /* bytes 8-11  */
+    uint32_t len_lba;   /* bytes 12-15 */
+} __attribute__((__packed__));
+
+struct pc_boot_record {
+    uint8_t code[440];                                      /* bytes 0-439   */
+    uint32_t disk_sig;                                      /* bytes 440-443 */
+    uint16_t pad;                                           /* bytes 444-445 */
+    struct pc_partition ptable[PC_NUM_BOOT_RECORD_PARTS];   /* bytes 446-509 */
+    uint16_t mbr_sig;                                       /* bytes 510-511 */
+} __attribute__((__packed__));
+
+struct part_info {
+    char *name;
+    uint8_t flags;
+    uint8_t type;
+    uint32_t len_kb;       /* in 1K-bytes */
+    uint32_t start_lba;    /* the LBA where this partition begins */
+};
+
+struct disk_info {
+    char *device;
+    uint8_t scheme;
+    int sect_size;       /* expected sector size in bytes. MUST BE POWER OF 2 */
+    uint32_t skip_lba;   /* in sectors (1 unit of LBA) */
+    uint32_t num_lba;    /* the size of the disk in LBA units */
+    struct part_info *part_lst;
+    int num_parts;
+};
+
+struct write_list {
+    struct write_list *next;
+    loff_t offset;
+    uint32_t len;
+    uint8_t data[0];
+};
+
+
+struct write_list *alloc_wl(uint32_t data_len);
+void free_wl(struct write_list *item);
+struct write_list *wlist_add(struct write_list **lst, struct write_list *item);
+void wlist_free(struct write_list *lst);
+int wlist_commit(int fd, struct write_list *lst, int test);
+
+struct disk_info *load_diskconfig(const char *fn, char *path_override);
+int dump_disk_config(struct disk_info *dinfo);
+int apply_disk_config(struct disk_info *dinfo, int test);
+char *find_part_device(struct disk_info *dinfo, const char *name);
+int process_disk_config(struct disk_info *dinfo);
+struct part_info *find_part(struct disk_info *dinfo, const char *name);
+
+int write_raw_image(const char *dst, const char *src, loff_t offset, int test);
+
+/* For MBR partition schemes */
+struct write_list *config_mbr(struct disk_info *dinfo);
+char *find_mbr_part(struct disk_info *dinfo, const char *name);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __LIBS_DISKCONFIG_H */
diff --git a/package/utils/adbd/src/include/hardware/qemu.c b/package/utils/adbd/src/include/hardware/qemu.c
new file mode 100755
index 0000000..de77cff
--- /dev/null
+++ b/package/utils/adbd/src/include/hardware/qemu.c
@@ -0,0 +1,401 @@
+/*
+ * 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.
+ */
+
+/* this file contains various functions used by all libhardware modules
+ * that support QEMU emulation
+ */
+#include "qemu.h"
+#define  LOG_TAG  "hardware-qemu"
+#include <cutils/log.h>
+#include <cutils/properties.h>
+#include <cutils/sockets.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <termios.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#define  QEMU_DEBUG  0
+
+#if QEMU_DEBUG
+#  define  D(...)   ALOGD(__VA_ARGS__)
+#else
+#  define  D(...)   ((void)0)
+#endif
+
+#include "qemu_pipe.h"
+
+int
+qemu_check(void)
+{
+    static int  in_qemu = -1;
+
+    if (__builtin_expect(in_qemu < 0,0)) {
+        char  propBuf[PROPERTY_VALUE_MAX];
+        property_get("ro.kernel.qemu", propBuf, "");
+        in_qemu = (propBuf[0] == '1');
+    }
+    return in_qemu;
+}
+
+static int
+qemu_fd_write( int  fd, const char*  cmd, int  len )
+{
+    int  len2;
+    do {
+        len2 = write(fd, cmd, len);
+    } while (len2 < 0 && errno == EINTR);
+    return len2;
+}
+
+static int
+qemu_fd_read( int  fd, char*  buff, int  len )
+{
+    int  len2;
+    do {
+        len2 = read(fd, buff, len);
+    } while (len2 < 0 && errno == EINTR);
+    return len2;
+}
+
+static int
+qemu_channel_open_qemud_pipe( QemuChannel*  channel,
+                              const char*   name )
+{
+    int   fd;
+    char  pipe_name[512];
+
+    snprintf(pipe_name, sizeof(pipe_name), "qemud:%s", name);
+    fd = qemu_pipe_open(pipe_name);
+    if (fd < 0) {
+        D("no qemud pipe: %s", strerror(errno));
+        return -1;
+    }
+
+    channel->is_qemud = 1;
+    channel->fd       = fd;
+    return 0;
+}
+
+static int
+qemu_channel_open_qemud( QemuChannel*  channel,
+                         const char*   name )
+{
+    int   fd, ret, namelen = strlen(name);
+    char  answer[2];
+
+    fd = socket_local_client( "qemud",
+                              ANDROID_SOCKET_NAMESPACE_RESERVED,
+                              SOCK_STREAM );
+    if (fd < 0) {
+        D("no qemud control socket: %s", strerror(errno));
+        return -1;
+    }
+
+    /* send service name to connect */
+    if (qemu_fd_write(fd, name, namelen) != namelen) {
+        D("can't send service name to qemud: %s",
+           strerror(errno));
+        close(fd);
+        return -1;
+    }
+
+    /* read answer from daemon */
+    if (qemu_fd_read(fd, answer, 2) != 2 ||
+        answer[0] != 'O' || answer[1] != 'K') {
+        D("cant' connect to %s service through qemud", name);
+        close(fd);
+        return -1;
+    }
+
+    channel->is_qemud = 1;
+    channel->fd       = fd;
+    return 0;
+}
+
+
+static int
+qemu_channel_open_qemud_old( QemuChannel*  channel,
+                             const char*   name )
+{
+    int  fd;
+
+    snprintf(channel->device, sizeof channel->device,
+                "qemud_%s", name);
+
+    fd = socket_local_client( channel->device,
+                              ANDROID_SOCKET_NAMESPACE_RESERVED,
+                              SOCK_STREAM );
+    if (fd < 0) {
+        D("no '%s' control socket available: %s",
+            channel->device, strerror(errno));
+        return -1;
+    }
+
+    close(fd);
+    channel->is_qemud_old = 1;
+    return 0;
+}
+
+
+static int
+qemu_channel_open_tty( QemuChannel*  channel,
+                       const char*   name,
+                       int           mode )
+{
+    char   key[PROPERTY_KEY_MAX];
+    char   prop[PROPERTY_VALUE_MAX];
+    int    ret;
+
+    ret = snprintf(key, sizeof key, "ro.kernel.android.%s", name);
+    if (ret >= (int)sizeof key)
+        return -1;
+
+    if (property_get(key, prop, "") == 0) {
+        D("no kernel-provided %s device name", name);
+        return -1;
+    }
+
+    ret = snprintf(channel->device, sizeof channel->device,
+                    "/dev/%s", prop);
+    if (ret >= (int)sizeof channel->device) {
+        D("%s device name too long: '%s'", name, prop);
+        return -1;
+    }
+
+    channel->is_tty = !memcmp("/dev/tty", channel->device, 8);
+    return 0;
+}
+
+int
+qemu_channel_open( QemuChannel*  channel,
+                   const char*   name,
+                   int           mode )
+{
+    int  fd = -1;
+
+    /* initialize the channel is needed */
+    if (!channel->is_inited)
+    {
+        channel->is_inited = 1;
+
+        do {
+            if (qemu_channel_open_qemud_pipe(channel, name) == 0)
+                break;
+
+            if (qemu_channel_open_qemud(channel, name) == 0)
+                break;
+
+            if (qemu_channel_open_qemud_old(channel, name) == 0)
+                break;
+
+            if (qemu_channel_open_tty(channel, name, mode) == 0)
+                break;
+
+            channel->is_available = 0;
+            return -1;
+        } while (0);
+
+        channel->is_available = 1;
+    }
+
+    /* try to open the file */
+    if (!channel->is_available) {
+        errno = ENOENT;
+        return -1;
+    }
+
+    if (channel->is_qemud) {
+        return dup(channel->fd);
+    }
+
+    if (channel->is_qemud_old) {
+        do {
+            fd = socket_local_client( channel->device,
+                                      ANDROID_SOCKET_NAMESPACE_RESERVED,
+                                      SOCK_STREAM );
+        } while (fd < 0 && errno == EINTR);
+    }
+    else /* /dev/ttySn ? */
+    {
+        do {
+            fd = open(channel->device, mode);
+        } while (fd < 0 && errno == EINTR);
+
+        /* disable ECHO on serial lines */
+        if (fd >= 0 && channel->is_tty) {
+            struct termios  ios;
+            tcgetattr( fd, &ios );
+            ios.c_lflag = 0;  /* disable ECHO, ICANON, etc... */
+            tcsetattr( fd, TCSANOW, &ios );
+        }
+    }
+    return fd;
+}
+
+
+static int
+qemu_command_vformat( char*        buffer,
+                      int          buffer_size,
+                      const char*  format,
+                      va_list      args )
+{
+    char     header[5];
+    int      len;
+
+    if (buffer_size < 6)
+        return -1;
+
+    len = vsnprintf(buffer+4, buffer_size-4, format, args);
+    if (len >= buffer_size-4)
+        return -1;
+
+    snprintf(header, sizeof header, "%04x", len);
+    memcpy(buffer, header, 4);
+    return len + 4;
+}
+
+extern int
+qemu_command_format( char*        buffer,
+                     int          buffer_size,
+                     const char*  format,
+                     ... )
+{
+    va_list  args;
+    int      ret;
+
+    va_start(args, format);
+    ret = qemu_command_format(buffer, buffer_size, format, args);
+    va_end(args);
+    return ret;
+}
+
+
+static int
+qemu_control_fd(void)
+{
+    static QemuChannel  channel[1];
+    int                 fd;
+
+    fd = qemu_channel_open( channel, "hw-control", O_RDWR );
+    if (fd < 0) {
+        D("%s: could not open control channel: %s", __FUNCTION__,
+          strerror(errno));
+    }
+    return fd;
+}
+
+static int
+qemu_control_send(const char*  cmd, int  len)
+{
+    int  fd, len2;
+
+    if (len < 0) {
+        errno = EINVAL;
+        return -1;
+    }
+
+    fd = qemu_control_fd();
+    if (fd < 0)
+        return -1;
+
+    len2 = qemu_fd_write(fd, cmd, len);
+    close(fd);
+    if (len2 != len) {
+        D("%s: could not send everything %d < %d",
+          __FUNCTION__, len2, len);
+        return -1;
+    }
+    return 0;
+}
+
+
+int
+qemu_control_command( const char*  fmt, ... )
+{
+    va_list  args;
+    char     command[256];
+    int      len, fd;
+
+    va_start(args, fmt);
+    len = qemu_command_vformat( command, sizeof command, fmt, args );
+    va_end(args);
+
+    if (len < 0 || len >= (int)sizeof command) {
+        if (len < 0) {
+            D("%s: could not send: %s", __FUNCTION__, strerror(errno));
+        } else {
+            D("%s: too large %d > %d", __FUNCTION__, len, (int)(sizeof command));
+        }
+        errno = EINVAL;
+        return -1;
+    }
+
+    return qemu_control_send( command, len );
+}
+
+extern int  qemu_control_query( const char*  question, int  questionlen,
+                                char*        answer,   int  answersize )
+{
+    int   ret, fd, len, result = -1;
+    char  header[5], *end;
+
+    if (questionlen <= 0) {
+        errno = EINVAL;
+        return -1;
+    }
+
+    fd = qemu_control_fd();
+    if (fd < 0)
+        return -1;
+
+    ret = qemu_fd_write( fd, question, questionlen );
+    if (ret != questionlen) {
+        D("%s: could not write all: %d < %d", __FUNCTION__,
+          ret, questionlen);
+        goto Exit;
+    }
+
+    /* read a 4-byte header giving the length of the following content */
+    ret = qemu_fd_read( fd, header, 4 );
+    if (ret != 4) {
+        D("%s: could not read header (%d != 4)",
+          __FUNCTION__, ret);
+        goto Exit;
+    }
+
+    header[4] = 0;
+    len = strtol( header, &end,  16 );
+    if ( len < 0 || end == NULL || end != header+4 || len > answersize ) {
+        D("%s: could not parse header: '%s'",
+          __FUNCTION__, header);
+        goto Exit;
+    }
+
+    /* read the answer */
+    ret = qemu_fd_read( fd, answer, len );
+    if (ret != len) {
+        D("%s: could not read all of answer %d < %d",
+          __FUNCTION__, ret, len);
+        goto Exit;
+    }
+
+    result = len;
+
+Exit:
+    close(fd);
+    return result;
+}
diff --git a/package/utils/adbd/src/include/hardware/qemu.h b/package/utils/adbd/src/include/hardware/qemu.h
new file mode 100755
index 0000000..d3c9f0c
--- /dev/null
+++ b/package/utils/adbd/src/include/hardware/qemu.h
@@ -0,0 +1,112 @@
+/*
+ * 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.
+ */
+#ifndef _libs_hardware_qemu_h
+#define _libs_hardware_qemu_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef QEMU_HARDWARE
+
+/* returns 1 iff we're running in the emulator */
+extern int  qemu_check(void);
+
+/* a structure used to hold enough state to connect to a given
+ * QEMU communication channel, either through a qemud socket or
+ * a serial port.
+ *
+ * initialize the structure by zero-ing it out
+ */
+typedef struct {
+    char   is_inited;
+    char   is_available;
+    char   is_qemud;
+    char   is_qemud_old;
+    char   is_tty;
+    int    fd;
+    char   device[32];
+} QemuChannel;
+
+/* try to open a qemu communication channel.
+ * returns a file descriptor on success, or -1 in case of
+ * error.
+ *
+ * 'channel' must be a QemuChannel structure that is empty
+ * on the first call. You can call this function several
+ * time to re-open the channel using the same 'channel'
+ * object to speed things a bit.
+ */
+extern int  qemu_channel_open( QemuChannel*  channel,
+                               const char*   name,
+                               int           mode );
+
+/* create a command made of a 4-hexchar prefix followed
+ * by the content. the prefix contains the content's length
+ * in hexadecimal coding.
+ *
+ * 'buffer' must be at last 6 bytes
+ * returns -1 in case of overflow, or the command's total length
+ * otherwise (i.e. content length + 4)
+ */
+extern int  qemu_command_format( char*        buffer,
+                                 int          buffer_size,
+                                 const char*  format,
+                                 ... );
+
+/* directly sends a command through the 'hw-control' channel.
+ * this will open the channel, send the formatted command, then
+ * close the channel automatically.
+ * returns 0 on success, or -1 on error.
+ */
+extern int  qemu_control_command( const char*  fmt, ... );
+
+/* sends a question to the hw-control channel, then receive an answer in
+ * a user-allocated buffer. returns the length of the answer, or -1
+ * in case of error.
+ *
+ * 'question' *must* have been formatted through qemu_command_format
+ */
+extern int  qemu_control_query( const char*  question, int  questionlen,
+                                char*        answer,   int  answersize );
+
+#endif /* QEMU_HARDWARE */
+
+/* use QEMU_FALLBACK(call) to call a QEMU-specific callback  */
+/* use QEMU_FALLBACK_VOID(call) if the function returns void */
+#ifdef QEMU_HARDWARE
+#  define  QEMU_FALLBACK(x)  \
+    do { \
+        if (qemu_check()) \
+            return qemu_ ## x ; \
+    } while (0)
+#  define  QEMU_FALLBACK_VOID(x)  \
+    do { \
+        if (qemu_check()) { \
+            qemu_ ## x ; \
+            return; \
+        } \
+    } while (0)
+#else
+#  define  QEMU_FALLBACK(x)       ((void)0)
+#  define  QEMU_FALLBACK_VOID(x)  ((void)0)
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _libs_hardware_qemu_h */
diff --git a/package/utils/adbd/src/include/hardware/qemu_pipe.h b/package/utils/adbd/src/include/hardware/qemu_pipe.h
new file mode 100755
index 0000000..68febf8
--- /dev/null
+++ b/package/utils/adbd/src/include/hardware/qemu_pipe.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2011 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 ANDROID_INCLUDE_HARDWARE_QEMU_PIPE_H
+#define ANDROID_INCLUDE_HARDWARE_QEMU_PIPE_H
+
+//#include <sys/cdefs.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <pthread.h>  /* for pthread_once() */
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+
+#ifndef D
+#  define  D(...)   do{}while(0)
+#endif
+
+/*
+ * TEMP_FAILURE_RETRY is defined by some, but not all, versions of
+ * <unistd.h>. (Alas, it is not as standard as we'd hoped!) So, if it's
+ * not already defined, then define it here.
+ */
+#ifndef TEMP_FAILURE_RETRY
+/* Used to retry syscalls that can return EINTR. */
+#define TEMP_FAILURE_RETRY(exp) ({         \
+    typeof (exp) _rc;                      \
+    do {                                   \
+        _rc = (exp);                       \
+    } while (_rc == -1 && errno == EINTR); \
+    _rc; })
+#endif
+
+/* Try to open a new Qemu fast-pipe. This function returns a file descriptor
+ * that can be used to communicate with a named service managed by the
+ * emulator.
+ *
+ * This file descriptor can be used as a standard pipe/socket descriptor.
+ *
+ * 'pipeName' is the name of the emulator service you want to connect to.
+ * E.g. 'opengles' or 'camera'.
+ *
+ * On success, return a valid file descriptor
+ * Returns -1 on error, and errno gives the error code, e.g.:
+ *
+ *    EINVAL  -> unknown/unsupported pipeName
+ *    ENOSYS  -> fast pipes not available in this system.
+ *
+ * ENOSYS should never happen, except if you're trying to run within a
+ * misconfigured emulator.
+ *
+ * You should be able to open several pipes to the same pipe service,
+ * except for a few special cases (e.g. GSM modem), where EBUSY will be
+ * returned if more than one client tries to connect to it.
+ */
+static __inline__ int
+qemu_pipe_open(const char*  pipeName)
+{
+    char  buff[256];
+    int   buffLen;
+    int   fd, ret;
+
+    if (pipeName == NULL || pipeName[0] == '\0') {
+        errno = EINVAL;
+        return -1;
+    }
+
+    snprintf(buff, sizeof buff, "pipe:%s", pipeName);
+
+    fd = open("/dev/qemu_pipe", O_RDWR);
+    if (fd < 0) {
+        D("%s: Could not open /dev/qemu_pipe: %s", __FUNCTION__, strerror(errno));
+        //errno = ENOSYS;
+        return -1;
+    }
+
+    buffLen = strlen(buff);
+
+    ret = TEMP_FAILURE_RETRY(write(fd, buff, buffLen+1));
+    if (ret != buffLen+1) {
+        D("%s: Could not connect to %s pipe service: %s", __FUNCTION__, pipeName, strerror(errno));
+        if (ret == 0) {
+            errno = ECONNRESET;
+        } else if (ret > 0) {
+            errno = EINVAL;
+        }
+        return -1;
+    }
+
+    return fd;
+}
+
+#endif /* ANDROID_INCLUDE_HARDWARE_QEMUD_PIPE_H */
diff --git a/package/utils/adbd/src/include/log/event_tag_map.h b/package/utils/adbd/src/include/log/event_tag_map.h
new file mode 100644
index 0000000..1653c61
--- /dev/null
+++ b/package/utils/adbd/src/include/log/event_tag_map.h
@@ -0,0 +1,50 @@
+/*
+ * 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 _LIBS_CUTILS_EVENTTAGMAP_H
+#define _LIBS_CUTILS_EVENTTAGMAP_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define EVENT_TAG_MAP_FILE  "/system/etc/event-log-tags"
+
+struct EventTagMap;
+typedef struct EventTagMap EventTagMap;
+
+/*
+ * Open the specified file as an event log tag map.
+ *
+ * Returns NULL on failure.
+ */
+EventTagMap* android_openEventTagMap(const char* fileName);
+
+/*
+ * Close the map.
+ */
+void android_closeEventTagMap(EventTagMap* map);
+
+/*
+ * Look up a tag by index.  Returns the tag string, or NULL if not found.
+ */
+const char* android_lookupEventTag(const EventTagMap* map, int tag);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*_LIBS_CUTILS_EVENTTAGMAP_H*/
diff --git a/package/utils/adbd/src/include/log/log.h b/package/utils/adbd/src/include/log/log.h
new file mode 100644
index 0000000..5b76c1a
--- /dev/null
+++ b/package/utils/adbd/src/include/log/log.h
@@ -0,0 +1,574 @@
+/*
+ * Copyright (C) 2005-2014 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.
+ */
+
+//
+// C/C++ logging functions.  See the logging documentation for API details.
+//
+// We'd like these to be available from C code (in case we import some from
+// somewhere), so this has a C interface.
+//
+// The output will be correct when the log file is shared between multiple
+// threads and/or multiple processes so long as the operating system
+// supports O_APPEND.  These calls have mutex-protected data structures
+// and so are NOT reentrant.  Do not use LOG in a signal handler.
+//
+#ifndef _LIBS_LOG_LOG_H
+#define _LIBS_LOG_LOG_H
+
+#include <sys/types.h>
+#ifdef HAVE_PTHREADS
+#include <pthread.h>
+#endif
+#include <stdarg.h>
+#include <stdio.h>
+#include <time.h>
+#include <unistd.h>
+#include <log/logd.h>
+#include <log/uio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// ---------------------------------------------------------------------
+
+/*
+ * Normally we strip ALOGV (VERBOSE messages) from release builds.
+ * You can modify this (for example with "#define LOG_NDEBUG 0"
+ * at the top of your source file) to change that behavior.
+ */
+#ifndef LOG_NDEBUG
+#ifdef NDEBUG
+#define LOG_NDEBUG 1
+#else
+#define LOG_NDEBUG 0
+#endif
+#endif
+
+/*
+ * This is the local tag used for the following simplified
+ * logging macros.  You can change this preprocessor definition
+ * before using the other macros to change the tag.
+ */
+#ifndef LOG_TAG
+#define LOG_TAG NULL
+#endif
+
+// ---------------------------------------------------------------------
+
+/*
+ * Simplified macro to send a verbose log message using the current LOG_TAG.
+ */
+#ifndef ALOGV
+#define __ALOGV(...) ((void)ALOG(LOG_VERBOSE, LOG_TAG, __VA_ARGS__))
+#if LOG_NDEBUG
+#define ALOGV(...) do { if (0) { __ALOGV(__VA_ARGS__); } } while (0)
+#else
+#define ALOGV(...) __ALOGV(__VA_ARGS__)
+#endif
+#endif
+
+#define CONDITION(cond)     (__builtin_expect((cond)!=0, 0))
+
+#ifndef ALOGV_IF
+#if LOG_NDEBUG
+#define ALOGV_IF(cond, ...)   ((void)0)
+#else
+#define ALOGV_IF(cond, ...) \
+    ( (CONDITION(cond)) \
+    ? ((void)ALOG(LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) \
+    : (void)0 )
+#endif
+#endif
+
+/*
+ * Simplified macro to send a debug log message using the current LOG_TAG.
+ */
+#ifndef ALOGD
+#define ALOGD(...) ((void)ALOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__))
+#endif
+
+#ifndef ALOGD_IF
+#define ALOGD_IF(cond, ...) \
+    ( (CONDITION(cond)) \
+    ? ((void)ALOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__)) \
+    : (void)0 )
+#endif
+
+/*
+ * Simplified macro to send an info log message using the current LOG_TAG.
+ */
+#ifndef ALOGI
+#define ALOGI(...) ((void)ALOG(LOG_INFO, LOG_TAG, __VA_ARGS__))
+#endif
+
+#ifndef ALOGI_IF
+#define ALOGI_IF(cond, ...) \
+    ( (CONDITION(cond)) \
+    ? ((void)ALOG(LOG_INFO, LOG_TAG, __VA_ARGS__)) \
+    : (void)0 )
+#endif
+
+/*
+ * Simplified macro to send a warning log message using the current LOG_TAG.
+ */
+#ifndef ALOGW
+#define ALOGW(...) ((void)ALOG(LOG_WARN, LOG_TAG, __VA_ARGS__))
+#endif
+
+#ifndef ALOGW_IF
+#define ALOGW_IF(cond, ...) \
+    ( (CONDITION(cond)) \
+    ? ((void)ALOG(LOG_WARN, LOG_TAG, __VA_ARGS__)) \
+    : (void)0 )
+#endif
+
+/*
+ * Simplified macro to send an error log message using the current LOG_TAG.
+ */
+#ifndef ALOGE
+#define ALOGE(...) ((void)ALOG(LOG_ERROR, LOG_TAG, __VA_ARGS__))
+#endif
+
+#ifndef ALOGE_IF
+#define ALOGE_IF(cond, ...) \
+    ( (CONDITION(cond)) \
+    ? ((void)ALOG(LOG_ERROR, LOG_TAG, __VA_ARGS__)) \
+    : (void)0 )
+#endif
+
+// ---------------------------------------------------------------------
+
+/*
+ * Conditional based on whether the current LOG_TAG is enabled at
+ * verbose priority.
+ */
+#ifndef IF_ALOGV
+#if LOG_NDEBUG
+#define IF_ALOGV() if (false)
+#else
+#define IF_ALOGV() IF_ALOG(LOG_VERBOSE, LOG_TAG)
+#endif
+#endif
+
+/*
+ * Conditional based on whether the current LOG_TAG is enabled at
+ * debug priority.
+ */
+#ifndef IF_ALOGD
+#define IF_ALOGD() IF_ALOG(LOG_DEBUG, LOG_TAG)
+#endif
+
+/*
+ * Conditional based on whether the current LOG_TAG is enabled at
+ * info priority.
+ */
+#ifndef IF_ALOGI
+#define IF_ALOGI() IF_ALOG(LOG_INFO, LOG_TAG)
+#endif
+
+/*
+ * Conditional based on whether the current LOG_TAG is enabled at
+ * warn priority.
+ */
+#ifndef IF_ALOGW
+#define IF_ALOGW() IF_ALOG(LOG_WARN, LOG_TAG)
+#endif
+
+/*
+ * Conditional based on whether the current LOG_TAG is enabled at
+ * error priority.
+ */
+#ifndef IF_ALOGE
+#define IF_ALOGE() IF_ALOG(LOG_ERROR, LOG_TAG)
+#endif
+
+
+// ---------------------------------------------------------------------
+
+/*
+ * Simplified macro to send a verbose system log message using the current LOG_TAG.
+ */
+#ifndef SLOGV
+#define __SLOGV(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__))
+#if LOG_NDEBUG
+#define SLOGV(...) do { if (0) { __SLOGV(__VA_ARGS__); } } while (0)
+#else
+#define SLOGV(...) __SLOGV(__VA_ARGS__)
+#endif
+#endif
+
+#define CONDITION(cond)     (__builtin_expect((cond)!=0, 0))
+
+#ifndef SLOGV_IF
+#if LOG_NDEBUG
+#define SLOGV_IF(cond, ...)   ((void)0)
+#else
+#define SLOGV_IF(cond, ...) \
+    ( (CONDITION(cond)) \
+    ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) \
+    : (void)0 )
+#endif
+#endif
+
+/*
+ * Simplified macro to send a debug system log message using the current LOG_TAG.
+ */
+#ifndef SLOGD
+#define SLOGD(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__))
+#endif
+
+#ifndef SLOGD_IF
+#define SLOGD_IF(cond, ...) \
+    ( (CONDITION(cond)) \
+    ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)) \
+    : (void)0 )
+#endif
+
+/*
+ * Simplified macro to send an info system log message using the current LOG_TAG.
+ */
+#ifndef SLOGI
+#define SLOGI(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__))
+#endif
+
+#ifndef SLOGI_IF
+#define SLOGI_IF(cond, ...) \
+    ( (CONDITION(cond)) \
+    ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)) \
+    : (void)0 )
+#endif
+
+/*
+ * Simplified macro to send a warning system log message using the current LOG_TAG.
+ */
+#ifndef SLOGW
+#define SLOGW(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__))
+#endif
+
+#ifndef SLOGW_IF
+#define SLOGW_IF(cond, ...) \
+    ( (CONDITION(cond)) \
+    ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)) \
+    : (void)0 )
+#endif
+
+/*
+ * Simplified macro to send an error system log message using the current LOG_TAG.
+ */
+#ifndef SLOGE
+#define SLOGE(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__))
+#endif
+
+#ifndef SLOGE_IF
+#define SLOGE_IF(cond, ...) \
+    ( (CONDITION(cond)) \
+    ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)) \
+    : (void)0 )
+#endif
+
+// ---------------------------------------------------------------------
+
+/*
+ * Simplified macro to send a verbose radio log message using the current LOG_TAG.
+ */
+#ifndef RLOGV
+#define __RLOGV(...) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__))
+#if LOG_NDEBUG
+#define RLOGV(...) do { if (0) { __RLOGV(__VA_ARGS__); } } while (0)
+#else
+#define RLOGV(...) __RLOGV(__VA_ARGS__)
+#endif
+#endif
+
+#define CONDITION(cond)     (__builtin_expect((cond)!=0, 0))
+
+#ifndef RLOGV_IF
+#if LOG_NDEBUG
+#define RLOGV_IF(cond, ...)   ((void)0)
+#else
+#define RLOGV_IF(cond, ...) \
+    ( (CONDITION(cond)) \
+    ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) \
+    : (void)0 )
+#endif
+#endif
+
+/*
+ * Simplified macro to send a debug radio log message using the current LOG_TAG.
+ */
+#ifndef RLOGD
+#define RLOGD(...) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__))
+#endif
+
+#ifndef RLOGD_IF
+#define RLOGD_IF(cond, ...) \
+    ( (CONDITION(cond)) \
+    ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)) \
+    : (void)0 )
+#endif
+
+/*
+ * Simplified macro to send an info radio log message using the current LOG_TAG.
+ */
+#ifndef RLOGI
+#define RLOGI(...) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__))
+#endif
+
+#ifndef RLOGI_IF
+#define RLOGI_IF(cond, ...) \
+    ( (CONDITION(cond)) \
+    ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)) \
+    : (void)0 )
+#endif
+
+/*
+ * Simplified macro to send a warning radio log message using the current LOG_TAG.
+ */
+#ifndef RLOGW
+#define RLOGW(...) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__))
+#endif
+
+#ifndef RLOGW_IF
+#define RLOGW_IF(cond, ...) \
+    ( (CONDITION(cond)) \
+    ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)) \
+    : (void)0 )
+#endif
+
+/*
+ * Simplified macro to send an error radio log message using the current LOG_TAG.
+ */
+#ifndef RLOGE
+#define RLOGE(...) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__))
+#endif
+
+#ifndef RLOGE_IF
+#define RLOGE_IF(cond, ...) \
+    ( (CONDITION(cond)) \
+    ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)) \
+    : (void)0 )
+#endif
+
+
+// ---------------------------------------------------------------------
+
+/*
+ * Log a fatal error.  If the given condition fails, this stops program
+ * execution like a normal assertion, but also generating the given message.
+ * It is NOT stripped from release builds.  Note that the condition test
+ * is -inverted- from the normal assert() semantics.
+ */
+#ifndef LOG_ALWAYS_FATAL_IF
+#define LOG_ALWAYS_FATAL_IF(cond, ...) \
+    ( (CONDITION(cond)) \
+    ? ((void)android_printAssert(#cond, LOG_TAG, ## __VA_ARGS__)) \
+    : (void)0 )
+#endif
+
+#ifndef LOG_ALWAYS_FATAL
+#define LOG_ALWAYS_FATAL(...) \
+    ( ((void)android_printAssert(NULL, LOG_TAG, ## __VA_ARGS__)) )
+#endif
+
+/*
+ * Versions of LOG_ALWAYS_FATAL_IF and LOG_ALWAYS_FATAL that
+ * are stripped out of release builds.
+ */
+#if LOG_NDEBUG
+
+#ifndef LOG_FATAL_IF
+#define LOG_FATAL_IF(cond, ...) ((void)0)
+#endif
+#ifndef LOG_FATAL
+#define LOG_FATAL(...) ((void)0)
+#endif
+
+#else
+
+#ifndef LOG_FATAL_IF
+#define LOG_FATAL_IF(cond, ...) LOG_ALWAYS_FATAL_IF(cond, ## __VA_ARGS__)
+#endif
+#ifndef LOG_FATAL
+#define LOG_FATAL(...) LOG_ALWAYS_FATAL(__VA_ARGS__)
+#endif
+
+#endif
+
+/*
+ * Assertion that generates a log message when the assertion fails.
+ * Stripped out of release builds.  Uses the current LOG_TAG.
+ */
+#ifndef ALOG_ASSERT
+#define ALOG_ASSERT(cond, ...) LOG_FATAL_IF(!(cond), ## __VA_ARGS__)
+//#define ALOG_ASSERT(cond) LOG_FATAL_IF(!(cond), "Assertion failed: " #cond)
+#endif
+
+// ---------------------------------------------------------------------
+
+/*
+ * Basic log message macro.
+ *
+ * Example:
+ *  ALOG(LOG_WARN, NULL, "Failed with error %d", errno);
+ *
+ * The second argument may be NULL or "" to indicate the "global" tag.
+ */
+#ifndef ALOG
+#define ALOG(priority, tag, ...) \
+    LOG_PRI(ANDROID_##priority, tag, __VA_ARGS__)
+#endif
+
+/*
+ * Log macro that allows you to specify a number for the priority.
+ */
+#ifndef LOG_PRI
+#define LOG_PRI(priority, tag, ...) \
+    android_printLog(priority, tag, __VA_ARGS__)
+#endif
+
+/*
+ * Log macro that allows you to pass in a varargs ("args" is a va_list).
+ */
+#ifndef LOG_PRI_VA
+#define LOG_PRI_VA(priority, tag, fmt, args) \
+    android_vprintLog(priority, NULL, tag, fmt, args)
+#endif
+
+/*
+ * Conditional given a desired logging priority and tag.
+ */
+#ifndef IF_ALOG
+#define IF_ALOG(priority, tag) \
+    if (android_testLog(ANDROID_##priority, tag))
+#endif
+
+// ---------------------------------------------------------------------
+
+/*
+ * Event logging.
+ */
+
+/*
+ * Event log entry types.  These must match up with the declarations in
+ * java/android/android/util/EventLog.java.
+ */
+typedef enum {
+    EVENT_TYPE_INT      = 0,
+    EVENT_TYPE_LONG     = 1,
+    EVENT_TYPE_STRING   = 2,
+    EVENT_TYPE_LIST     = 3,
+} AndroidEventLogType;
+#define sizeof_AndroidEventLogType sizeof(typeof_AndroidEventLogType)
+#define typeof_AndroidEventLogType unsigned char
+
+#ifndef LOG_EVENT_INT
+#define LOG_EVENT_INT(_tag, _value) {                                       \
+        int intBuf = _value;                                                \
+        (void) android_btWriteLog(_tag, EVENT_TYPE_INT, &intBuf,            \
+            sizeof(intBuf));                                                \
+    }
+#endif
+#ifndef LOG_EVENT_LONG
+#define LOG_EVENT_LONG(_tag, _value) {                                      \
+        long long longBuf = _value;                                         \
+        (void) android_btWriteLog(_tag, EVENT_TYPE_LONG, &longBuf,          \
+            sizeof(longBuf));                                               \
+    }
+#endif
+#ifndef LOG_EVENT_STRING
+#define LOG_EVENT_STRING(_tag, _value)                                      \
+    ((void) 0)  /* not implemented -- must combine len with string */
+#endif
+/* TODO: something for LIST */
+
+/*
+ * ===========================================================================
+ *
+ * The stuff in the rest of this file should not be used directly.
+ */
+
+#define android_printLog(prio, tag, fmt...) \
+    __android_log_print(prio, tag, fmt)
+
+#define android_vprintLog(prio, cond, tag, fmt...) \
+    __android_log_vprint(prio, tag, fmt)
+
+/* XXX Macros to work around syntax errors in places where format string
+ * arg is not passed to ALOG_ASSERT, LOG_ALWAYS_FATAL or LOG_ALWAYS_FATAL_IF
+ * (happens only in debug builds).
+ */
+
+/* Returns 2nd arg.  Used to substitute default value if caller's vararg list
+ * is empty.
+ */
+#define __android_second(dummy, second, ...)     second
+
+/* If passed multiple args, returns ',' followed by all but 1st arg, otherwise
+ * returns nothing.
+ */
+#define __android_rest(first, ...)               , ## __VA_ARGS__
+
+#define android_printAssert(cond, tag, fmt...) \
+    __android_log_assert(cond, tag, \
+        __android_second(0, ## fmt, NULL) __android_rest(fmt))
+
+#define android_writeLog(prio, tag, text) \
+    __android_log_write(prio, tag, text)
+
+#define android_bWriteLog(tag, payload, len) \
+    __android_log_bwrite(tag, payload, len)
+#define android_btWriteLog(tag, type, payload, len) \
+    __android_log_btwrite(tag, type, payload, len)
+
+// TODO: remove these prototypes and their users
+#define android_testLog(prio, tag) (1)
+#define android_writevLog(vec,num) do{}while(0)
+#define android_write1Log(str,len) do{}while (0)
+#define android_setMinPriority(tag, prio) do{}while(0)
+//#define android_logToCallback(func) do{}while(0)
+#define android_logToFile(tag, file) (0)
+#define android_logToFd(tag, fd) (0)
+
+typedef enum log_id {
+    LOG_ID_MIN = 0,
+
+    LOG_ID_MAIN = 0,
+    LOG_ID_RADIO = 1,
+    LOG_ID_EVENTS = 2,
+    LOG_ID_SYSTEM = 3,
+    LOG_ID_CRASH = 4,
+
+    LOG_ID_MAX
+} log_id_t;
+#define sizeof_log_id_t sizeof(typeof_log_id_t)
+#define typeof_log_id_t unsigned char
+
+/*
+ * Send a simple string to the log.
+ */
+int __android_log_buf_write(int bufID, int prio, const char *tag, const char *text);
+int __android_log_buf_print(int bufID, int prio, const char *tag, const char *fmt, ...)
+#if defined(__GNUC__)
+    __attribute__((__format__(printf, 4, 5)))
+#endif
+    ;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LIBS_LOG_LOG_H */
diff --git a/package/utils/adbd/src/include/log/log_read.h b/package/utils/adbd/src/include/log/log_read.h
new file mode 100644
index 0000000..946711a
--- /dev/null
+++ b/package/utils/adbd/src/include/log/log_read.h
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2013-2014 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 _LIBS_LOG_LOG_READ_H
+#define _LIBS_LOG_LOG_READ_H
+
+#include <stdint.h>
+#include <time.h>
+
+/* struct log_time is a wire-format variant of struct timespec */
+#define NS_PER_SEC 1000000000ULL
+
+#ifdef __cplusplus
+
+// NB: do NOT define a copy constructor. This will result in structure
+// no longer being compatible with pass-by-value which is desired
+// efficient behavior. Also, pass-by-reference breaks C/C++ ABI.
+struct log_time {
+public:
+    uint32_t tv_sec; // good to Feb 5 2106
+    uint32_t tv_nsec;
+
+    static const uint32_t tv_sec_max = 0xFFFFFFFFUL;
+    static const uint32_t tv_nsec_max = 999999999UL;
+
+    log_time(const timespec &T)
+    {
+        tv_sec = T.tv_sec;
+        tv_nsec = T.tv_nsec;
+    }
+    log_time(uint32_t sec, uint32_t nsec)
+    {
+        tv_sec = sec;
+        tv_nsec = nsec;
+    }
+    static const timespec EPOCH;
+    log_time()
+    {
+    }
+    log_time(clockid_t id)
+    {
+        timespec T;
+        clock_gettime(id, &T);
+        tv_sec = T.tv_sec;
+        tv_nsec = T.tv_nsec;
+    }
+    log_time(const char *T)
+    {
+        const uint8_t *c = (const uint8_t *) T;
+        tv_sec = c[0] | (c[1] << 8) | (c[2] << 16) | (c[3] << 24);
+        tv_nsec = c[4] | (c[5] << 8) | (c[6] << 16) | (c[7] << 24);
+    }
+
+    // timespec
+    bool operator== (const timespec &T) const
+    {
+        return (tv_sec == static_cast<uint32_t>(T.tv_sec))
+            && (tv_nsec == static_cast<uint32_t>(T.tv_nsec));
+    }
+    bool operator!= (const timespec &T) const
+    {
+        return !(*this == T);
+    }
+    bool operator< (const timespec &T) const
+    {
+        return (tv_sec < static_cast<uint32_t>(T.tv_sec))
+            || ((tv_sec == static_cast<uint32_t>(T.tv_sec))
+                && (tv_nsec < static_cast<uint32_t>(T.tv_nsec)));
+    }
+    bool operator>= (const timespec &T) const
+    {
+        return !(*this < T);
+    }
+    bool operator> (const timespec &T) const
+    {
+        return (tv_sec > static_cast<uint32_t>(T.tv_sec))
+            || ((tv_sec == static_cast<uint32_t>(T.tv_sec))
+                && (tv_nsec > static_cast<uint32_t>(T.tv_nsec)));
+    }
+    bool operator<= (const timespec &T) const
+    {
+        return !(*this > T);
+    }
+    log_time operator-= (const timespec &T);
+    log_time operator- (const timespec &T) const
+    {
+        log_time local(*this);
+        return local -= T;
+    }
+
+    // log_time
+    bool operator== (const log_time &T) const
+    {
+        return (tv_sec == T.tv_sec) && (tv_nsec == T.tv_nsec);
+    }
+    bool operator!= (const log_time &T) const
+    {
+        return !(*this == T);
+    }
+    bool operator< (const log_time &T) const
+    {
+        return (tv_sec < T.tv_sec)
+            || ((tv_sec == T.tv_sec) && (tv_nsec < T.tv_nsec));
+    }
+    bool operator>= (const log_time &T) const
+    {
+        return !(*this < T);
+    }
+    bool operator> (const log_time &T) const
+    {
+        return (tv_sec > T.tv_sec)
+            || ((tv_sec == T.tv_sec) && (tv_nsec > T.tv_nsec));
+    }
+    bool operator<= (const log_time &T) const
+    {
+        return !(*this > T);
+    }
+    log_time operator-= (const log_time &T);
+    log_time operator- (const log_time &T) const
+    {
+        log_time local(*this);
+        return local -= T;
+    }
+
+    uint64_t nsec() const
+    {
+        return static_cast<uint64_t>(tv_sec) * NS_PER_SEC + tv_nsec;
+    }
+
+    static const char default_format[];
+
+    // Add %#q for the fraction of a second to the standard library functions
+    char *strptime(const char *s, const char *format = default_format);
+} __attribute__((__packed__));
+
+#else
+
+typedef struct log_time {
+    uint32_t tv_sec;
+    uint32_t tv_nsec;
+} __attribute__((__packed__)) log_time;
+
+#endif
+
+#endif /* define _LIBS_LOG_LOG_READ_H */
diff --git a/package/utils/adbd/src/include/log/logd.h b/package/utils/adbd/src/include/log/logd.h
new file mode 100644
index 0000000..379c373
--- /dev/null
+++ b/package/utils/adbd/src/include/log/logd.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2009 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 _ANDROID_CUTILS_LOGD_H
+#define _ANDROID_CUTILS_LOGD_H
+
+/* the stable/frozen log-related definitions have been
+ * moved to this header, which is exposed by the NDK
+ */
+#include <android/log.h>
+
+/* the rest is only used internally by the system */
+#include <time.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <sys/types.h>
+#ifdef HAVE_PTHREADS
+#include <pthread.h>
+#endif
+#include <log/uio.h>
+#include <stdarg.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int __android_log_bwrite(int32_t tag, const void *payload, size_t len);
+int __android_log_btwrite(int32_t tag, char type, const void *payload,
+    size_t len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LOGD_H */
diff --git a/package/utils/adbd/src/include/log/logger.h b/package/utils/adbd/src/include/log/logger.h
new file mode 100644
index 0000000..53be1d3
--- /dev/null
+++ b/package/utils/adbd/src/include/log/logger.h
@@ -0,0 +1,189 @@
+/*
+**
+** Copyright 2007-2014, The Android Open Source Project
+**
+** This file is dual licensed.  It may be redistributed and/or modified
+** under the terms of the Apache 2.0 License OR version 2 of the GNU
+** General Public License.
+*/
+
+#ifndef _LIBS_LOG_LOGGER_H
+#define _LIBS_LOG_LOGGER_H
+
+#include <stdint.h>
+#include <log/log.h>
+#include <log/log_read.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * The userspace structure for version 1 of the logger_entry ABI.
+ * This structure is returned to userspace by the kernel logger
+ * driver unless an upgrade to a newer ABI version is requested.
+ */
+struct logger_entry {
+    uint16_t    len;    /* length of the payload */
+    uint16_t    __pad;  /* no matter what, we get 2 bytes of padding */
+    int32_t     pid;    /* generating process's pid */
+    int32_t     tid;    /* generating process's tid */
+    int32_t     sec;    /* seconds since Epoch */
+    int32_t     nsec;   /* nanoseconds */
+    char        msg[0]; /* the entry's payload */
+} __attribute__((__packed__));
+
+/*
+ * The userspace structure for version 2 of the logger_entry ABI.
+ * This structure is returned to userspace if ioctl(LOGGER_SET_VERSION)
+ * is called with version==2; or used with the user space log daemon.
+ */
+struct logger_entry_v2 {
+    uint16_t    len;       /* length of the payload */
+    uint16_t    hdr_size;  /* sizeof(struct logger_entry_v2) */
+    int32_t     pid;       /* generating process's pid */
+    int32_t     tid;       /* generating process's tid */
+    int32_t     sec;       /* seconds since Epoch */
+    int32_t     nsec;      /* nanoseconds */
+    uint32_t    euid;      /* effective UID of logger */
+    char        msg[0];    /* the entry's payload */
+} __attribute__((__packed__));
+
+struct logger_entry_v3 {
+    uint16_t    len;       /* length of the payload */
+    uint16_t    hdr_size;  /* sizeof(struct logger_entry_v3) */
+    int32_t     pid;       /* generating process's pid */
+    int32_t     tid;       /* generating process's tid */
+    int32_t     sec;       /* seconds since Epoch */
+    int32_t     nsec;      /* nanoseconds */
+    uint32_t    lid;       /* log id of the payload */
+    char        msg[0];    /* the entry's payload */
+} __attribute__((__packed__));
+
+/*
+ * The maximum size of the log entry payload that can be
+ * written to the logger. An attempt to write more than
+ * this amount will result in a truncated log entry.
+ */
+#define LOGGER_ENTRY_MAX_PAYLOAD	4076
+
+/*
+ * The maximum size of a log entry which can be read from the
+ * kernel logger driver. An attempt to read less than this amount
+ * may result in read() returning EINVAL.
+ */
+#define LOGGER_ENTRY_MAX_LEN		(5*1024)
+
+#define NS_PER_SEC 1000000000ULL
+
+struct log_msg {
+    union {
+        unsigned char buf[LOGGER_ENTRY_MAX_LEN + 1];
+        struct logger_entry_v3 entry;
+        struct logger_entry_v3 entry_v3;
+        struct logger_entry_v2 entry_v2;
+        struct logger_entry    entry_v1;
+    } __attribute__((aligned(4)));
+#ifdef __cplusplus
+    /* Matching log_time operators */
+    bool operator== (const log_msg &T) const
+    {
+        return (entry.sec == T.entry.sec) && (entry.nsec == T.entry.nsec);
+    }
+    bool operator!= (const log_msg &T) const
+    {
+        return !(*this == T);
+    }
+    bool operator< (const log_msg &T) const
+    {
+        return (entry.sec < T.entry.sec)
+            || ((entry.sec == T.entry.sec)
+             && (entry.nsec < T.entry.nsec));
+    }
+    bool operator>= (const log_msg &T) const
+    {
+        return !(*this < T);
+    }
+    bool operator> (const log_msg &T) const
+    {
+        return (entry.sec > T.entry.sec)
+            || ((entry.sec == T.entry.sec)
+             && (entry.nsec > T.entry.nsec));
+    }
+    bool operator<= (const log_msg &T) const
+    {
+        return !(*this > T);
+    }
+    uint64_t nsec() const
+    {
+        return static_cast<uint64_t>(entry.sec) * NS_PER_SEC + entry.nsec;
+    }
+
+    /* packet methods */
+    log_id_t id()
+    {
+        return (log_id_t) entry.lid;
+    }
+    char *msg()
+    {
+        return entry.hdr_size ? (char *) buf + entry.hdr_size : entry_v1.msg;
+    }
+    unsigned int len()
+    {
+        return (entry.hdr_size ? entry.hdr_size : sizeof(entry_v1)) + entry.len;
+    }
+#endif
+};
+
+struct logger;
+
+log_id_t android_logger_get_id(struct logger *logger);
+
+int android_logger_clear(struct logger *logger);
+long android_logger_get_log_size(struct logger *logger);
+int android_logger_set_log_size(struct logger *logger, unsigned long size);
+long android_logger_get_log_readable_size(struct logger *logger);
+int android_logger_get_log_version(struct logger *logger);
+
+struct logger_list;
+
+ssize_t android_logger_get_statistics(struct logger_list *logger_list,
+                                      char *buf, size_t len);
+ssize_t android_logger_get_prune_list(struct logger_list *logger_list,
+                                      char *buf, size_t len);
+int android_logger_set_prune_list(struct logger_list *logger_list,
+                                  char *buf, size_t len);
+
+struct logger_list *android_logger_list_alloc(int mode,
+                                              unsigned int tail,
+                                              pid_t pid);
+struct logger_list *android_logger_list_alloc_time(int mode,
+                                                   log_time start,
+                                                   pid_t pid);
+void android_logger_list_free(struct logger_list *logger_list);
+/* In the purest sense, the following two are orthogonal interfaces */
+int android_logger_list_read(struct logger_list *logger_list,
+                             struct log_msg *log_msg);
+
+/* Multiple log_id_t opens */
+struct logger *android_logger_open(struct logger_list *logger_list,
+                                   log_id_t id);
+#define android_logger_close android_logger_free
+/* Single log_id_t open */
+struct logger_list *android_logger_list_open(log_id_t id,
+                                             int mode,
+                                             unsigned int tail,
+                                             pid_t pid);
+#define android_logger_list_close android_logger_list_free
+
+/*
+ * log_id_t helpers
+ */
+log_id_t android_name_to_log_id(const char *logName);
+const char *android_log_id_to_name(log_id_t log_id);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LIBS_LOG_LOGGER_H */
diff --git a/package/utils/adbd/src/include/log/logprint.h b/package/utils/adbd/src/include/log/logprint.h
new file mode 100644
index 0000000..481c96e
--- /dev/null
+++ b/package/utils/adbd/src/include/log/logprint.h
@@ -0,0 +1,156 @@
+/*
+ * 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 _LOGPRINT_H
+#define _LOGPRINT_H
+
+#include <log/log.h>
+#include <log/logger.h>
+#include <log/event_tag_map.h>
+#include <pthread.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+    FORMAT_OFF = 0,
+    FORMAT_BRIEF,
+    FORMAT_PROCESS,
+    FORMAT_TAG,
+    FORMAT_THREAD,
+    FORMAT_RAW,
+    FORMAT_TIME,
+    FORMAT_THREADTIME,
+    FORMAT_LONG,
+} AndroidLogPrintFormat;
+
+typedef struct AndroidLogFormat_t AndroidLogFormat;
+
+typedef struct AndroidLogEntry_t {
+    time_t tv_sec;
+    long tv_nsec;
+    android_LogPriority priority;
+    int32_t pid;
+    int32_t tid;
+    const char * tag;
+    size_t messageLen;
+    const char * message;
+} AndroidLogEntry;
+
+AndroidLogFormat *android_log_format_new();
+
+void android_log_format_free(AndroidLogFormat *p_format);
+
+void android_log_setPrintFormat(AndroidLogFormat *p_format, 
+        AndroidLogPrintFormat format);
+
+/**
+ * Returns FORMAT_OFF on invalid string
+ */
+AndroidLogPrintFormat android_log_formatFromString(const char *s);
+
+/** 
+ * filterExpression: a single filter expression
+ * eg "AT:d"
+ *
+ * returns 0 on success and -1 on invalid expression
+ *
+ * Assumes single threaded execution
+ *
+ */
+
+int android_log_addFilterRule(AndroidLogFormat *p_format, 
+        const char *filterExpression);
+
+
+/** 
+ * filterString: a whitespace-separated set of filter expressions 
+ * eg "AT:d *:i"
+ *
+ * returns 0 on success and -1 on invalid expression
+ *
+ * Assumes single threaded execution
+ *
+ */
+
+int android_log_addFilterString(AndroidLogFormat *p_format,
+        const char *filterString);
+
+
+/** 
+ * returns 1 if this log line should be printed based on its priority
+ * and tag, and 0 if it should not
+ */
+int android_log_shouldPrintLine (
+        AndroidLogFormat *p_format, const char *tag, android_LogPriority pri);
+
+
+/**
+ * Splits a wire-format buffer into an AndroidLogEntry
+ * entry allocated by caller. Pointers will point directly into buf
+ *
+ * Returns 0 on success and -1 on invalid wire format (entry will be
+ * in unspecified state)
+ */
+int android_log_processLogBuffer(struct logger_entry *buf,
+                                 AndroidLogEntry *entry);
+
+/**
+ * Like android_log_processLogBuffer, but for binary logs.
+ *
+ * If "map" is non-NULL, it will be used to convert the log tag number
+ * into a string.
+ */
+int android_log_processBinaryLogBuffer(struct logger_entry *buf,
+    AndroidLogEntry *entry, const EventTagMap* map, char* messageBuf,
+    int messageBufLen);
+
+
+/**
+ * Formats a log message into a buffer
+ *
+ * Uses defaultBuffer if it can, otherwise malloc()'s a new buffer
+ * If return value != defaultBuffer, caller must call free()
+ * Returns NULL on malloc error
+ */
+
+char *android_log_formatLogLine (    
+    AndroidLogFormat *p_format,
+    char *defaultBuffer,
+    size_t defaultBufferSize,
+    const AndroidLogEntry *p_line,
+    size_t *p_outLength);
+
+
+/**
+ * Either print or do not print log line, based on filter
+ *
+ * Assumes single threaded execution
+ *
+ */
+int android_log_printLogLine(
+    AndroidLogFormat *p_format,
+    int fd,
+    const AndroidLogEntry *entry);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /*_LOGPRINT_H*/
diff --git a/package/utils/adbd/src/include/log/uio.h b/package/utils/adbd/src/include/log/uio.h
new file mode 100644
index 0000000..a71f515
--- /dev/null
+++ b/package/utils/adbd/src/include/log/uio.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2007-2014 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.
+ */
+
+//
+// implementation of sys/uio.h for platforms that don't have it (Win32)
+//
+#ifndef _LIBS_CUTILS_UIO_H
+#define _LIBS_CUTILS_UIO_H
+
+#ifdef HAVE_SYS_UIO_H
+#include <sys/uio.h>
+#else
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stddef.h>
+
+struct iovec {
+    void*  iov_base;
+    size_t iov_len;
+};
+
+extern int  readv( int  fd, struct iovec*  vecs, int  count );
+extern int  writev( int  fd, const struct iovec*  vecs, int  count );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !HAVE_SYS_UIO_H */
+
+#endif /* _LIBS_UTILS_UIO_H */
+
diff --git a/package/utils/adbd/src/include/memtrack/memtrack.h b/package/utils/adbd/src/include/memtrack/memtrack.h
new file mode 100644
index 0000000..0f1f85e
--- /dev/null
+++ b/package/utils/adbd/src/include/memtrack/memtrack.h
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2013 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 _LIBMEMTRACK_MEMTRACK_H_
+#define _LIBMEMTRACK_MEMTRACK_H_
+
+#include <sys/types.h>
+#include <stddef.h>
+#include <cutils/compiler.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * struct memtrack_proc
+ *
+ * an opaque handle to the memory stats on a process.
+ * Created with memtrack_proc_new, destroyed by
+ * memtrack_proc_destroy.  Can be reused multiple times with
+ * memtrack_proc_get.
+ */
+struct memtrack_proc;
+
+/**
+ * memtrack_init
+ *
+ * Must be called once before calling any other functions.  After this function
+ * is called, everything else is thread-safe.
+ *
+ * Returns 0 on success, -errno on error.
+ */
+int memtrack_init(void);
+
+/**
+ * memtrack_proc_new
+ *
+ * Return a new handle to hold process memory stats.
+ *
+ * Returns NULL on error.
+ */
+struct memtrack_proc *memtrack_proc_new(void);
+
+/**
+ * memtrack_proc_destroy
+ *
+ * Free all memory associated with a process memory stats handle.
+ */
+void memtrack_proc_destroy(struct memtrack_proc *p);
+
+/**
+ * memtrack_proc_get
+ *
+ * Fill a process memory stats handle with data about the given pid.  Can be
+ * called on a handle that was just allocated with memtrack_proc_new,
+ * or on a handle that has been previously passed to memtrack_proc_get
+ * to replace the data with new data on the same or another process.  It is
+ * expected that the second call on the same handle should not require
+ * allocating any new memory.
+ *
+ * Returns 0 on success, -errno on error.
+ */
+int memtrack_proc_get(struct memtrack_proc *p, pid_t pid);
+
+/**
+ * memtrack_proc_graphics_total
+ *
+ * Return total amount of memory that has been allocated for use as window
+ * buffers.  Does not differentiate between memory that has already been
+ * accounted for by reading /proc/pid/smaps and memory that has not been
+ * accounted for.
+ *
+ * Returns non-negative size in bytes on success, -errno on error.
+ */
+ssize_t memtrack_proc_graphics_total(struct memtrack_proc *p);
+
+/**
+ * memtrack_proc_graphics_pss
+ *
+ * Return total amount of memory that has been allocated for use as window
+ * buffers, but has not already been accounted for by reading /proc/pid/smaps.
+ * Memory that is shared across processes may already be divided by the
+ * number of processes that share it (preferred), or may be charged in full to
+ * every process that shares it, depending on the capabilities of the driver.
+ *
+ * Returns non-negative size in bytes on success, -errno on error.
+ */
+ssize_t memtrack_proc_graphics_pss(struct memtrack_proc *p);
+
+/**
+ * memtrack_proc_gl_total
+ *
+ * Same as memtrack_proc_graphics_total, but counts GL memory (which
+ * should not overlap with graphics memory) instead of graphics memory.
+ *
+ * Returns non-negative size in bytes on success, -errno on error.
+ */
+ssize_t memtrack_proc_gl_total(struct memtrack_proc *p);
+
+/**
+ * memtrack_proc_gl_pss
+ *
+ * Same as memtrack_proc_graphics_total, but counts GL memory (which
+ * should not overlap with graphics memory) instead of graphics memory.
+ *
+ * Returns non-negative size in bytes on success, -errno on error.
+ */
+ssize_t memtrack_proc_gl_pss(struct memtrack_proc *p);
+
+/**
+ * memtrack_proc_gl_total
+ *
+ * Same as memtrack_proc_graphics_total, but counts miscellaneous memory
+ * not tracked by gl or graphics calls above.
+ *
+ * Returns non-negative size in bytes on success, -errno on error.
+ */
+ssize_t memtrack_proc_other_total(struct memtrack_proc *p);
+
+/**
+ * memtrack_proc_gl_pss
+ *
+ * Same as memtrack_proc_graphics_total, but counts miscellaneous memory
+ * not tracked by gl or graphics calls above.
+ *
+ * Returns non-negative size in bytes on success, -errno on error.
+ */
+ssize_t memtrack_proc_other_pss(struct memtrack_proc *p);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/package/utils/adbd/src/include/mincrypt/dsa_sig.h b/package/utils/adbd/src/include/mincrypt/dsa_sig.h
new file mode 100644
index 0000000..b0d91cd
--- /dev/null
+++ b/package/utils/adbd/src/include/mincrypt/dsa_sig.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2013 The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Google Inc. nor the names of its contributors may
+ *       be used to endorse or promote products derived from this software
+ *       without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SYSTEM_CORE_INCLUDE_MINCRYPT_DSA_SIG_H_
+#define SYSTEM_CORE_INCLUDE_MINCRYPT_DSA_SIG_H_
+
+#include "mincrypt/p256.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Returns 0 if input sig is not a valid ASN.1 sequence
+int dsa_sig_unpack(unsigned char* sig, int sig_len, p256_int* r_int, p256_int* s_int);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SYSTEM_CORE_INCLUDE_MINCRYPT_DSA_SIG_H_ */
diff --git a/package/utils/adbd/src/include/mincrypt/hash-internal.h b/package/utils/adbd/src/include/mincrypt/hash-internal.h
new file mode 100644
index 0000000..c813b44
--- /dev/null
+++ b/package/utils/adbd/src/include/mincrypt/hash-internal.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2007 The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Google Inc. nor the names of its contributors may
+ *       be used to endorse or promote products derived from this software
+ *       without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SYSTEM_CORE_INCLUDE_MINCRYPT_HASH_INTERNAL_H_
+#define SYSTEM_CORE_INCLUDE_MINCRYPT_HASH_INTERNAL_H_
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif  // __cplusplus
+
+struct HASH_CTX;  // forward decl
+
+typedef struct HASH_VTAB {
+  void (* const init)(struct HASH_CTX*);
+  void (* const update)(struct HASH_CTX*, const void*, int);
+  const uint8_t* (* const final)(struct HASH_CTX*);
+  const uint8_t* (* const hash)(const void*, int, uint8_t*);
+  int size;
+} HASH_VTAB;
+
+typedef struct HASH_CTX {
+  const HASH_VTAB * f;
+  uint64_t count;
+  uint8_t buf[64];
+  uint32_t state[8];  // upto SHA2
+} HASH_CTX;
+
+#define HASH_init(ctx) (ctx)->f->init(ctx)
+#define HASH_update(ctx, data, len) (ctx)->f->update(ctx, data, len)
+#define HASH_final(ctx) (ctx)->f->final(ctx)
+#define HASH_hash(data, len, digest) (ctx)->f->hash(data, len, digest)
+#define HASH_size(ctx) (ctx)->f->size
+
+#ifdef __cplusplus
+}
+#endif  // __cplusplus
+
+#endif  // SYSTEM_CORE_INCLUDE_MINCRYPT_HASH_INTERNAL_H_
diff --git a/package/utils/adbd/src/include/mincrypt/p256.h b/package/utils/adbd/src/include/mincrypt/p256.h
new file mode 100644
index 0000000..465a1b9
--- /dev/null
+++ b/package/utils/adbd/src/include/mincrypt/p256.h
@@ -0,0 +1,162 @@
+/*
+ * Copyright 2013 The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Google Inc. nor the names of its contributors may
+ *       be used to endorse or promote products derived from this software
+ *       without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SYSTEM_CORE_INCLUDE_MINCRYPT_LITE_P256_H_
+#define SYSTEM_CORE_INCLUDE_MINCRYPT_LITE_P256_H_
+
+// Collection of routines manipulating 256 bit unsigned integers.
+// Just enough to implement ecdsa-p256 and related algorithms.
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define P256_BITSPERDIGIT 32
+#define P256_NDIGITS 8
+#define P256_NBYTES 32
+
+typedef int p256_err;
+typedef uint32_t p256_digit;
+typedef int32_t p256_sdigit;
+typedef uint64_t p256_ddigit;
+typedef int64_t p256_sddigit;
+
+// Defining p256_int as struct to leverage struct assigment.
+typedef struct {
+  p256_digit a[P256_NDIGITS];
+} p256_int;
+
+extern const p256_int SECP256r1_n;  // Curve order
+extern const p256_int SECP256r1_p;  // Curve prime
+extern const p256_int SECP256r1_b;  // Curve param
+
+// Initialize a p256_int to zero.
+void p256_init(p256_int* a);
+
+// Clear a p256_int to zero.
+void p256_clear(p256_int* a);
+
+// Return bit. Index 0 is least significant.
+int p256_get_bit(const p256_int* a, int index);
+
+// b := a % MOD
+void p256_mod(
+    const p256_int* MOD,
+    const p256_int* a,
+    p256_int* b);
+
+// c := a * (top_b | b) % MOD
+void p256_modmul(
+    const p256_int* MOD,
+    const p256_int* a,
+    const p256_digit top_b,
+    const p256_int* b,
+    p256_int* c);
+
+// b := 1 / a % MOD
+// MOD best be SECP256r1_n
+void p256_modinv(
+    const p256_int* MOD,
+    const p256_int* a,
+    p256_int* b);
+
+// b := 1 / a % MOD
+// MOD best be SECP256r1_n
+// Faster than p256_modinv()
+void p256_modinv_vartime(
+    const p256_int* MOD,
+    const p256_int* a,
+    p256_int* b);
+
+// b := a << (n % P256_BITSPERDIGIT)
+// Returns the bits shifted out of most significant digit.
+p256_digit p256_shl(const p256_int* a, int n, p256_int* b);
+
+// b := a >> (n % P256_BITSPERDIGIT)
+void p256_shr(const p256_int* a, int n, p256_int* b);
+
+int p256_is_zero(const p256_int* a);
+int p256_is_odd(const p256_int* a);
+int p256_is_even(const p256_int* a);
+
+// Returns -1, 0 or 1.
+int p256_cmp(const p256_int* a, const p256_int *b);
+
+// c: = a - b
+// Returns -1 on borrow.
+int p256_sub(const p256_int* a, const p256_int* b, p256_int* c);
+
+// c := a + b
+// Returns 1 on carry.
+int p256_add(const p256_int* a, const p256_int* b, p256_int* c);
+
+// c := a + (single digit)b
+// Returns carry 1 on carry.
+int p256_add_d(const p256_int* a, p256_digit b, p256_int* c);
+
+// ec routines.
+
+// {out_x,out_y} := nG
+void p256_base_point_mul(const p256_int *n,
+                         p256_int *out_x,
+                         p256_int *out_y);
+
+// {out_x,out_y} := n{in_x,in_y}
+void p256_point_mul(const p256_int *n,
+                    const p256_int *in_x,
+                    const p256_int *in_y,
+                    p256_int *out_x,
+                    p256_int *out_y);
+
+// {out_x,out_y} := n1G + n2{in_x,in_y}
+void p256_points_mul_vartime(
+    const p256_int *n1, const p256_int *n2,
+    const p256_int *in_x, const p256_int *in_y,
+    p256_int *out_x, p256_int *out_y);
+
+// Return whether point {x,y} is on curve.
+int p256_is_valid_point(const p256_int* x, const p256_int* y);
+
+// Outputs big-endian binary form. No leading zero skips.
+void p256_to_bin(const p256_int* src, uint8_t dst[P256_NBYTES]);
+
+// Reads from big-endian binary form,
+// thus pre-pad with leading zeros if short.
+void p256_from_bin(const uint8_t src[P256_NBYTES], p256_int* dst);
+
+#define P256_DIGITS(x) ((x)->a)
+#define P256_DIGIT(x,y) ((x)->a[y])
+
+#define P256_ZERO {{0}}
+#define P256_ONE {{1}}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  // SYSTEM_CORE_INCLUDE_MINCRYPT_LITE_P256_H_
diff --git a/package/utils/adbd/src/include/mincrypt/p256_ecdsa.h b/package/utils/adbd/src/include/mincrypt/p256_ecdsa.h
new file mode 100644
index 0000000..da339fa
--- /dev/null
+++ b/package/utils/adbd/src/include/mincrypt/p256_ecdsa.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2013 The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Google Inc. nor the names of its contributors may
+ *       be used to endorse or promote products derived from this software
+ *       without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SYSTEM_CORE_INCLUDE_MINCRYPT_P256_ECDSA_H_
+#define SYSTEM_CORE_INCLUDE_MINCRYPT_P256_ECDSA_H_
+
+// Using current directory as relative include path here since
+// this code typically gets lifted into a variety of build systems
+// and directory structures.
+#include "p256.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Returns 0 if {r,s} is not a signature on message for
+// public key {key_x,key_y}.
+//
+// Note: message is a p256_int.
+// Convert from a binary string using p256_from_bin().
+int p256_ecdsa_verify(const p256_int* key_x,
+                      const p256_int* key_y,
+                      const p256_int* message,
+                      const p256_int* r, const p256_int* s);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  // SYSTEM_CORE_INCLUDE_MINCRYPT_P256_ECDSA_H_
diff --git a/package/utils/adbd/src/include/mincrypt/rsa.h b/package/utils/adbd/src/include/mincrypt/rsa.h
new file mode 100644
index 0000000..3d0556b
--- /dev/null
+++ b/package/utils/adbd/src/include/mincrypt/rsa.h
@@ -0,0 +1,58 @@
+/* rsa.h
+**
+** Copyright 2008, The Android Open Source Project
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are met:
+**     * Redistributions of source code must retain the above copyright
+**       notice, this list of conditions and the following disclaimer.
+**     * Redistributions in binary form must reproduce the above copyright
+**       notice, this list of conditions and the following disclaimer in the
+**       documentation and/or other materials provided with the distribution.
+**     * Neither the name of Google Inc. nor the names of its contributors may
+**       be used to endorse or promote products derived from this software
+**       without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR
+** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+** EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef SYSTEM_CORE_INCLUDE_MINCRYPT_RSA_H_
+#define SYSTEM_CORE_INCLUDE_MINCRYPT_RSA_H_
+
+#include <inttypes.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define RSANUMBYTES 256           /* 2048 bit key length */
+#define RSANUMWORDS (RSANUMBYTES / sizeof(uint32_t))
+
+typedef struct RSAPublicKey {
+    int len;                  /* Length of n[] in number of uint32_t */
+    uint32_t n0inv;           /* -1 / n[0] mod 2^32 */
+    uint32_t n[RSANUMWORDS];  /* modulus as little endian array */
+    uint32_t rr[RSANUMWORDS]; /* R^2 as little endian array */
+    int exponent;             /* 3 or 65537 */
+} RSAPublicKey;
+
+int RSA_verify(const RSAPublicKey *key,
+               const uint8_t* signature,
+               const int len,
+               const uint8_t* hash,
+               const int hash_len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // SYSTEM_CORE_INCLUDE_MINCRYPT_RSA_H_
diff --git a/package/utils/adbd/src/include/mincrypt/sha.h b/package/utils/adbd/src/include/mincrypt/sha.h
new file mode 100644
index 0000000..ef60aab
--- /dev/null
+++ b/package/utils/adbd/src/include/mincrypt/sha.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2005 The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Google Inc. nor the names of its contributors may
+ *       be used to endorse or promote products derived from this software
+ *       without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef SYSTEM_CORE_INCLUDE_MINCRYPT_SHA1_H_
+#define SYSTEM_CORE_INCLUDE_MINCRYPT_SHA1_H_
+
+#include <stdint.h>
+#include "hash-internal.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+typedef HASH_CTX SHA_CTX;
+
+void SHA_init(SHA_CTX* ctx);
+void SHA_update(SHA_CTX* ctx, const void* data, int len);
+const uint8_t* SHA_final(SHA_CTX* ctx);
+
+// Convenience method. Returns digest address.
+// NOTE: *digest needs to hold SHA_DIGEST_SIZE bytes.
+const uint8_t* SHA_hash(const void* data, int len, uint8_t* digest);
+
+#define SHA_DIGEST_SIZE 20
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif  // SYSTEM_CORE_INCLUDE_MINCRYPT_SHA1_H_
diff --git a/package/utils/adbd/src/include/mincrypt/sha256.h b/package/utils/adbd/src/include/mincrypt/sha256.h
new file mode 100644
index 0000000..3a87c31
--- /dev/null
+++ b/package/utils/adbd/src/include/mincrypt/sha256.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2011 The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Google Inc. nor the names of its contributors may
+ *       be used to endorse or promote products derived from this software
+ *       without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SYSTEM_CORE_INCLUDE_MINCRYPT_SHA256_H_
+#define SYSTEM_CORE_INCLUDE_MINCRYPT_SHA256_H_
+
+#include <stdint.h>
+#include "hash-internal.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+typedef HASH_CTX SHA256_CTX;
+
+void SHA256_init(SHA256_CTX* ctx);
+void SHA256_update(SHA256_CTX* ctx, const void* data, int len);
+const uint8_t* SHA256_final(SHA256_CTX* ctx);
+
+// Convenience method. Returns digest address.
+const uint8_t* SHA256_hash(const void* data, int len, uint8_t* digest);
+
+#define SHA256_DIGEST_SIZE 32
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif  // SYSTEM_CORE_INCLUDE_MINCRYPT_SHA256_H_
diff --git a/package/utils/adbd/src/include/nativebridge/native_bridge.h b/package/utils/adbd/src/include/nativebridge/native_bridge.h
new file mode 100644
index 0000000..523dc49
--- /dev/null
+++ b/package/utils/adbd/src/include/nativebridge/native_bridge.h
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2014 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 NATIVE_BRIDGE_H_
+#define NATIVE_BRIDGE_H_
+
+#include "jni.h"
+#include <stdint.h>
+#include <sys/types.h>
+
+namespace android {
+
+struct NativeBridgeRuntimeCallbacks;
+struct NativeBridgeRuntimeValues;
+
+// Open the native bridge, if any. Should be called by Runtime::Init(). A null library filename
+// signals that we do not want to load a native bridge.
+bool LoadNativeBridge(const char* native_bridge_library_filename,
+                      const NativeBridgeRuntimeCallbacks* runtime_callbacks);
+
+// Quick check whether a native bridge will be needed. This is based off of the instruction set
+// of the process.
+bool NeedsNativeBridge(const char* instruction_set);
+
+// Do the early initialization part of the native bridge, if necessary. This should be done under
+// high privileges.
+bool PreInitializeNativeBridge(const char* app_data_dir, const char* instruction_set);
+
+// Initialize the native bridge, if any. Should be called by Runtime::DidForkFromZygote. The JNIEnv*
+// will be used to modify the app environment for the bridge.
+bool InitializeNativeBridge(JNIEnv* env, const char* instruction_set);
+
+// Unload the native bridge, if any. Should be called by Runtime::DidForkFromZygote.
+void UnloadNativeBridge();
+
+// Check whether a native bridge is available (opened or initialized). Requires a prior call to
+// LoadNativeBridge.
+bool NativeBridgeAvailable();
+
+// Check whether a native bridge is available (initialized). Requires a prior call to
+// LoadNativeBridge & InitializeNativeBridge.
+bool NativeBridgeInitialized();
+
+// Load a shared library that is supported by the native bridge.
+void* NativeBridgeLoadLibrary(const char* libpath, int flag);
+
+// Get a native bridge trampoline for specified native method.
+void* NativeBridgeGetTrampoline(void* handle, const char* name, const char* shorty, uint32_t len);
+
+// True if native library is valid and is for an ABI that is supported by native bridge.
+bool NativeBridgeIsSupported(const char* libpath);
+
+// Returns whether we have seen a native bridge error. This could happen because the library
+// was not found, rejected, could not be initialized and so on.
+//
+// This functionality is mainly for testing.
+bool NativeBridgeError();
+
+// Returns whether a given string is acceptable as a native bridge library filename.
+//
+// This functionality is exposed mainly for testing.
+bool NativeBridgeNameAcceptable(const char* native_bridge_library_filename);
+
+// Native bridge interfaces to runtime.
+struct NativeBridgeCallbacks {
+  // Version number of the interface.
+  uint32_t version;
+
+  // Initialize native bridge. Native bridge's internal implementation must ensure MT safety and
+  // that the native bridge is initialized only once. Thus it is OK to call this interface for an
+  // already initialized native bridge.
+  //
+  // Parameters:
+  //   runtime_cbs [IN] the pointer to NativeBridgeRuntimeCallbacks.
+  // Returns:
+  //   true iff initialization was successful.
+  bool (*initialize)(const NativeBridgeRuntimeCallbacks* runtime_cbs, const char* private_dir,
+                     const char* instruction_set);
+
+  // Load a shared library that is supported by the native bridge.
+  //
+  // Parameters:
+  //   libpath [IN] path to the shared library
+  //   flag [IN] the stardard RTLD_XXX defined in bionic dlfcn.h
+  // Returns:
+  //   The opaque handle of the shared library if sucessful, otherwise NULL
+  void* (*loadLibrary)(const char* libpath, int flag);
+
+  // Get a native bridge trampoline for specified native method. The trampoline has same
+  // sigature as the native method.
+  //
+  // Parameters:
+  //   handle [IN] the handle returned from loadLibrary
+  //   shorty [IN] short descriptor of native method
+  //   len [IN] length of shorty
+  // Returns:
+  //   address of trampoline if successful, otherwise NULL
+  void* (*getTrampoline)(void* handle, const char* name, const char* shorty, uint32_t len);
+
+  // Check whether native library is valid and is for an ABI that is supported by native bridge.
+  //
+  // Parameters:
+  //   libpath [IN] path to the shared library
+  // Returns:
+  //   TRUE if library is supported by native bridge, FALSE otherwise
+  bool (*isSupported)(const char* libpath);
+
+  // Provide environment values required by the app running with native bridge according to the
+  // instruction set.
+  //
+  // Parameters:
+  //    instruction_set [IN] the instruction set of the app
+  // Returns:
+  //    NULL if not supported by native bridge.
+  //    Otherwise, return all environment values to be set after fork.
+  const struct NativeBridgeRuntimeValues* (*getAppEnv)(const char* instruction_set);
+};
+
+// Runtime interfaces to native bridge.
+struct NativeBridgeRuntimeCallbacks {
+  // Get shorty of a Java method. The shorty is supposed to be persistent in memory.
+  //
+  // Parameters:
+  //   env [IN] pointer to JNIenv.
+  //   mid [IN] Java methodID.
+  // Returns:
+  //   short descriptor for method.
+  const char* (*getMethodShorty)(JNIEnv* env, jmethodID mid);
+
+  // Get number of native methods for specified class.
+  //
+  // Parameters:
+  //   env [IN] pointer to JNIenv.
+  //   clazz [IN] Java class object.
+  // Returns:
+  //   number of native methods.
+  uint32_t (*getNativeMethodCount)(JNIEnv* env, jclass clazz);
+
+  // Get at most 'method_count' native methods for specified class 'clazz'. Results are outputed
+  // via 'methods' [OUT]. The signature pointer in JNINativeMethod is reused as the method shorty.
+  //
+  // Parameters:
+  //   env [IN] pointer to JNIenv.
+  //   clazz [IN] Java class object.
+  //   methods [OUT] array of method with the name, shorty, and fnPtr.
+  //   method_count [IN] max number of elements in methods.
+  // Returns:
+  //   number of method it actually wrote to methods.
+  uint32_t (*getNativeMethods)(JNIEnv* env, jclass clazz, JNINativeMethod* methods,
+                               uint32_t method_count);
+};
+
+};  // namespace android
+
+#endif  // NATIVE_BRIDGE_H_
diff --git a/package/utils/adbd/src/include/netutils/dhcp.h b/package/utils/adbd/src/include/netutils/dhcp.h
new file mode 100644
index 0000000..a4f791d
--- /dev/null
+++ b/package/utils/adbd/src/include/netutils/dhcp.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2010, 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 _NETUTILS_DHCP_H_
+#define _NETUTILS_DHCP_H_
+
+#include <arpa/inet.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+extern int do_dhcp(char *iname);
+extern int dhcp_do_request(const char *ifname,
+                          char *ipaddr,
+                          char *gateway,
+                          uint32_t *prefixLength,
+                          char *dns[],
+                          char *server,
+                          uint32_t *lease,
+                          char *vendorInfo,
+                          char *domain,
+                          char *mtu);
+extern int dhcp_do_request_renew(const char *ifname,
+                                char *ipaddr,
+                                char *gateway,
+                                uint32_t *prefixLength,
+                                char *dns[],
+                                char *server,
+                                uint32_t *lease,
+                                char *vendorInfo,
+                                char *domain,
+                                char *mtu);
+extern int dhcp_stop(const char *ifname);
+extern int dhcp_release_lease(const char *ifname);
+extern char *dhcp_get_errmsg();
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _NETUTILS_DHCP_H_ */
diff --git a/package/utils/adbd/src/include/netutils/ifc.h b/package/utils/adbd/src/include/netutils/ifc.h
new file mode 100644
index 0000000..9233f87
--- /dev/null
+++ b/package/utils/adbd/src/include/netutils/ifc.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright 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.
+ */
+
+#ifndef _NETUTILS_IFC_H_
+#define _NETUTILS_IFC_H_
+
+//#include <sys/cdefs.h>
+#include <arpa/inet.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+extern int ifc_init(void);
+extern void ifc_close(void);
+
+extern int ifc_get_ifindex(const char *name, int *if_indexp);
+extern int ifc_get_hwaddr(const char *name, void *ptr);
+
+extern int ifc_up(const char *name);
+extern int ifc_down(const char *name);
+
+extern int ifc_enable(const char *ifname);
+extern int ifc_disable(const char *ifname);
+
+#define RESET_IPV4_ADDRESSES 0x01
+#define RESET_IPV6_ADDRESSES 0x02
+#define RESET_ALL_ADDRESSES  (RESET_IPV4_ADDRESSES | RESET_IPV6_ADDRESSES)
+extern int ifc_reset_connections(const char *ifname, const int reset_mask);
+
+extern int ifc_get_addr(const char *name, in_addr_t *addr);
+extern int ifc_set_addr(const char *name, in_addr_t addr);
+extern int ifc_add_address(const char *name, const char *address,
+                           int prefixlen);
+extern int ifc_del_address(const char *name, const char *address,
+                           int prefixlen);
+extern int ifc_set_prefixLength(const char *name, int prefixLength);
+extern int ifc_set_hwaddr(const char *name, const void *ptr);
+extern int ifc_clear_addresses(const char *name);
+
+/* This function is deprecated. Use ifc_add_route instead. */
+extern int ifc_add_host_route(const char *name, in_addr_t addr);
+extern int ifc_remove_host_routes(const char *name);
+extern int ifc_get_default_route(const char *ifname);
+/* This function is deprecated. Use ifc_add_route instead */
+extern int ifc_set_default_route(const char *ifname, in_addr_t gateway);
+/* This function is deprecated. Use ifc_add_route instead */
+extern int ifc_create_default_route(const char *name, in_addr_t addr);
+extern int ifc_remove_default_route(const char *ifname);
+extern int ifc_add_route(const char *name, const char *addr, int prefix_length,
+                         const char *gw);
+extern int ifc_remove_route(const char *ifname, const char *dst,
+                            int prefix_length, const char *gw);
+extern int ifc_get_info(const char *name, in_addr_t *addr, int *prefixLength,
+                        unsigned *flags);
+
+extern int ifc_configure(const char *ifname, in_addr_t address,
+                         uint32_t prefixLength, in_addr_t gateway,
+                         in_addr_t dns1, in_addr_t dns2);
+
+extern in_addr_t prefixLengthToIpv4Netmask(int prefix_length);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _NETUTILS_IFC_H_ */
diff --git a/package/utils/adbd/src/include/pixelflinger/format.h b/package/utils/adbd/src/include/pixelflinger/format.h
new file mode 100644
index 0000000..82eeca4
--- /dev/null
+++ b/package/utils/adbd/src/include/pixelflinger/format.h
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2005 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 ANDROID_PIXELFLINGER_FORMAT_H
+#define ANDROID_PIXELFLINGER_FORMAT_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+enum GGLPixelFormat {
+    // these constants need to match those
+    // in graphics/PixelFormat.java, ui/PixelFormat.h, BlitHardware.h
+    GGL_PIXEL_FORMAT_UNKNOWN    =   0,
+    GGL_PIXEL_FORMAT_NONE       =   0,
+
+    GGL_PIXEL_FORMAT_RGBA_8888   =   1,  // 4x8-bit ARGB
+    GGL_PIXEL_FORMAT_RGBX_8888   =   2,  // 3x8-bit RGB stored in 32-bit chunks
+    GGL_PIXEL_FORMAT_RGB_888     =   3,  // 3x8-bit RGB
+    GGL_PIXEL_FORMAT_RGB_565     =   4,  // 16-bit RGB
+    GGL_PIXEL_FORMAT_BGRA_8888   =   5,  // 4x8-bit BGRA
+    GGL_PIXEL_FORMAT_RGBA_5551   =   6,  // 16-bit RGBA
+    GGL_PIXEL_FORMAT_RGBA_4444   =   7,  // 16-bit RGBA
+
+    GGL_PIXEL_FORMAT_A_8         =   8,  // 8-bit A
+    GGL_PIXEL_FORMAT_L_8         =   9,  // 8-bit L (R=G=B = L)
+    GGL_PIXEL_FORMAT_LA_88       = 0xA,  // 16-bit LA
+    GGL_PIXEL_FORMAT_RGB_332     = 0xB,  // 8-bit RGB (non paletted)
+
+    // reserved range. don't use.
+    GGL_PIXEL_FORMAT_RESERVED_10 = 0x10,
+    GGL_PIXEL_FORMAT_RESERVED_11 = 0x11,
+    GGL_PIXEL_FORMAT_RESERVED_12 = 0x12,
+    GGL_PIXEL_FORMAT_RESERVED_13 = 0x13,
+    GGL_PIXEL_FORMAT_RESERVED_14 = 0x14,
+    GGL_PIXEL_FORMAT_RESERVED_15 = 0x15,
+    GGL_PIXEL_FORMAT_RESERVED_16 = 0x16,
+    GGL_PIXEL_FORMAT_RESERVED_17 = 0x17,
+
+    // reserved/special formats
+    GGL_PIXEL_FORMAT_Z_16       =  0x18,
+    GGL_PIXEL_FORMAT_S_8        =  0x19,
+    GGL_PIXEL_FORMAT_SZ_24      =  0x1A,
+    GGL_PIXEL_FORMAT_SZ_8       =  0x1B,
+
+    // reserved range. don't use.
+    GGL_PIXEL_FORMAT_RESERVED_20 = 0x20,
+    GGL_PIXEL_FORMAT_RESERVED_21 = 0x21,
+};
+
+enum GGLFormatComponents {
+	GGL_STENCIL_INDEX		= 0x1901,
+	GGL_DEPTH_COMPONENT		= 0x1902,
+	GGL_ALPHA				= 0x1906,
+	GGL_RGB					= 0x1907,
+	GGL_RGBA				= 0x1908,
+	GGL_LUMINANCE			= 0x1909,
+	GGL_LUMINANCE_ALPHA		= 0x190A,
+};
+
+enum GGLFormatComponentIndex {
+    GGL_INDEX_ALPHA   = 0,
+    GGL_INDEX_RED     = 1,
+    GGL_INDEX_GREEN   = 2,
+    GGL_INDEX_BLUE    = 3,
+    GGL_INDEX_STENCIL = 0,
+    GGL_INDEX_DEPTH   = 1,
+    GGL_INDEX_Y       = 0,
+    GGL_INDEX_CB      = 1,
+    GGL_INDEX_CR      = 2,
+};
+
+typedef struct {
+#ifdef __cplusplus
+    enum {
+        ALPHA   = GGL_INDEX_ALPHA,
+        RED     = GGL_INDEX_RED,
+        GREEN   = GGL_INDEX_GREEN,
+        BLUE    = GGL_INDEX_BLUE,
+        STENCIL = GGL_INDEX_STENCIL,
+        DEPTH   = GGL_INDEX_DEPTH,
+        LUMA    = GGL_INDEX_Y,
+        CHROMAB = GGL_INDEX_CB,
+        CHROMAR = GGL_INDEX_CR,
+    };
+    inline uint32_t mask(int i) const {
+            return ((1<<(c[i].h-c[i].l))-1)<<c[i].l;
+    }
+    inline uint32_t bits(int i) const {
+            return c[i].h - c[i].l;
+    }
+#endif
+	uint8_t     size;	// bytes per pixel
+    uint8_t     bitsPerPixel;
+    union {    
+        struct {
+            uint8_t     ah;		// alpha high bit position + 1
+            uint8_t     al;		// alpha low bit position
+            uint8_t     rh;		// red high bit position + 1
+            uint8_t     rl;		// red low bit position
+            uint8_t     gh;		// green high bit position + 1
+            uint8_t     gl;		// green low bit position
+            uint8_t     bh;		// blue high bit position + 1
+            uint8_t     bl;		// blue low bit position
+        };
+        struct {
+            uint8_t h;
+            uint8_t l;
+        } __attribute__((__packed__)) c[4];        
+    } __attribute__((__packed__));
+	uint16_t    components;	// GGLFormatComponents
+} GGLFormat;
+
+
+#ifdef __cplusplus
+extern "C" const GGLFormat* gglGetPixelFormatTable(size_t* numEntries = 0);
+#else
+const GGLFormat* gglGetPixelFormatTable(size_t* numEntries);
+#endif
+
+
+// ----------------------------------------------------------------------------
+
+#endif // ANDROID_PIXELFLINGER_FORMAT_H
diff --git a/package/utils/adbd/src/include/pixelflinger/pixelflinger.h b/package/utils/adbd/src/include/pixelflinger/pixelflinger.h
new file mode 100644
index 0000000..8a2b442
--- /dev/null
+++ b/package/utils/adbd/src/include/pixelflinger/pixelflinger.h
@@ -0,0 +1,330 @@
+/*
+ * 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 ANDROID_PIXELFLINGER_H
+#define ANDROID_PIXELFLINGER_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <pixelflinger/format.h>
+
+// GGL types
+
+typedef int8_t			GGLbyte;		// b
+typedef int16_t			GGLshort;		// s
+typedef int32_t			GGLint;			// i
+typedef ssize_t			GGLsizei;		// i
+typedef int32_t			GGLfixed;		// x
+typedef int32_t			GGLclampx;		// x
+typedef float			GGLfloat;		// f
+typedef float			GGLclampf;		// f
+typedef double			GGLdouble;		// d
+typedef double			GGLclampd;		// d
+typedef uint8_t			GGLubyte;		// ub
+typedef uint8_t			GGLboolean;		// ub
+typedef uint16_t		GGLushort;		// us
+typedef uint32_t		GGLuint;		// ui
+typedef unsigned int	GGLenum;		// ui
+typedef unsigned int	GGLbitfield;	// ui
+typedef void			GGLvoid;
+typedef int32_t         GGLfixed32;
+typedef	int32_t         GGLcolor;
+typedef int32_t         GGLcoord;
+
+// ----------------------------------------------------------------------------
+
+#define GGL_MAX_VIEWPORT_DIMS           4096
+#define GGL_MAX_TEXTURE_SIZE            4096
+#define GGL_MAX_ALIASED_POINT_SIZE      0x7FFFFFF
+#define GGL_MAX_SMOOTH_POINT_SIZE       2048
+#define GGL_MAX_SMOOTH_LINE_WIDTH       2048
+
+// ----------------------------------------------------------------------------
+
+// All these names are compatible with their OpenGL equivalents
+// some of them are listed only for completeness
+enum GGLNames {
+	GGL_FALSE						= 0,
+	GGL_TRUE						= 1,
+
+	// enable/disable
+    GGL_SCISSOR_TEST                = 0x0C11,
+	GGL_TEXTURE_2D					= 0x0DE1,
+	GGL_ALPHA_TEST					= 0x0BC0,
+	GGL_BLEND						= 0x0BE2,
+	GGL_COLOR_LOGIC_OP				= 0x0BF2,
+	GGL_DITHER						= 0x0BD0,
+	GGL_STENCIL_TEST				= 0x0B90,
+	GGL_DEPTH_TEST					= 0x0B71,
+    GGL_AA                          = 0x80000001,
+    GGL_W_LERP                      = 0x80000004,
+    GGL_POINT_SMOOTH_NICE           = 0x80000005,
+
+    // buffers, pixel drawing/reading
+    GGL_COLOR                       = 0x1800,
+    
+    // fog
+    GGL_FOG                         = 0x0B60,
+    
+	// shade model
+	GGL_FLAT						= 0x1D00,
+	GGL_SMOOTH						= 0x1D01,
+
+	// Texture parameter name
+	GGL_TEXTURE_MIN_FILTER			= 0x2801,
+	GGL_TEXTURE_MAG_FILTER			= 0x2800,
+	GGL_TEXTURE_WRAP_S				= 0x2802,
+	GGL_TEXTURE_WRAP_T				= 0x2803,
+	GGL_TEXTURE_WRAP_R				= 0x2804,
+
+	// Texture Filter	
+	GGL_NEAREST						= 0x2600,
+	GGL_LINEAR						= 0x2601,
+	GGL_NEAREST_MIPMAP_NEAREST		= 0x2700,
+	GGL_LINEAR_MIPMAP_NEAREST		= 0x2701,
+	GGL_NEAREST_MIPMAP_LINEAR		= 0x2702,
+	GGL_LINEAR_MIPMAP_LINEAR		= 0x2703,
+
+	// Texture Wrap Mode
+	GGL_CLAMP						= 0x2900,
+	GGL_REPEAT						= 0x2901,
+    GGL_CLAMP_TO_EDGE               = 0x812F,
+
+	// Texture Env Mode
+	GGL_REPLACE						= 0x1E01,
+	GGL_MODULATE					= 0x2100,
+	GGL_DECAL						= 0x2101,
+	GGL_ADD							= 0x0104,
+
+	// Texture Env Parameter
+	GGL_TEXTURE_ENV_MODE			= 0x2200,
+	GGL_TEXTURE_ENV_COLOR			= 0x2201,
+
+	// Texture Env Target
+	GGL_TEXTURE_ENV					= 0x2300,
+
+    // Texture coord generation
+    GGL_TEXTURE_GEN_MODE            = 0x2500,
+    GGL_S                           = 0x2000,
+    GGL_T                           = 0x2001,
+    GGL_R                           = 0x2002,
+    GGL_Q                           = 0x2003,
+    GGL_ONE_TO_ONE                  = 0x80000002,
+    GGL_AUTOMATIC                   = 0x80000003,
+
+    // AlphaFunction
+    GGL_NEVER                       = 0x0200,
+    GGL_LESS                        = 0x0201,
+    GGL_EQUAL                       = 0x0202,
+    GGL_LEQUAL                      = 0x0203,
+    GGL_GREATER                     = 0x0204,
+    GGL_NOTEQUAL                    = 0x0205,
+    GGL_GEQUAL                      = 0x0206,
+    GGL_ALWAYS                      = 0x0207,
+
+    // LogicOp
+    GGL_CLEAR                       = 0x1500,   // 0
+    GGL_AND                         = 0x1501,   // s & d
+    GGL_AND_REVERSE                 = 0x1502,   // s & ~d
+    GGL_COPY                        = 0x1503,   // s
+    GGL_AND_INVERTED                = 0x1504,   // ~s & d
+    GGL_NOOP                        = 0x1505,   // d
+    GGL_XOR                         = 0x1506,   // s ^ d
+    GGL_OR                          = 0x1507,   // s | d
+    GGL_NOR                         = 0x1508,   // ~(s | d)
+    GGL_EQUIV                       = 0x1509,   // ~(s ^ d)
+    GGL_INVERT                      = 0x150A,   // ~d
+    GGL_OR_REVERSE                  = 0x150B,   // s | ~d
+    GGL_COPY_INVERTED               = 0x150C,   // ~s 
+    GGL_OR_INVERTED                 = 0x150D,   // ~s | d
+    GGL_NAND                        = 0x150E,   // ~(s & d)
+    GGL_SET                         = 0x150F,   // 1
+
+	// blending equation & function
+	GGL_ZERO                        = 0,		// SD
+	GGL_ONE                         = 1,		// SD
+	GGL_SRC_COLOR                   = 0x0300,	//  D
+	GGL_ONE_MINUS_SRC_COLOR         = 0x0301,	//	D
+	GGL_SRC_ALPHA                   = 0x0302,	// SD
+	GGL_ONE_MINUS_SRC_ALPHA			= 0x0303,	// SD
+	GGL_DST_ALPHA					= 0x0304,	// SD
+	GGL_ONE_MINUS_DST_ALPHA			= 0x0305,	// SD
+	GGL_DST_COLOR					= 0x0306,	// S
+	GGL_ONE_MINUS_DST_COLOR			= 0x0307,	// S
+	GGL_SRC_ALPHA_SATURATE			= 0x0308,	// S
+    
+    // clear bits
+    GGL_DEPTH_BUFFER_BIT            = 0x00000100,
+    GGL_STENCIL_BUFFER_BIT          = 0x00000400,
+    GGL_COLOR_BUFFER_BIT            = 0x00004000,
+
+    // errors
+    GGL_NO_ERROR                    = 0,
+    GGL_INVALID_ENUM                = 0x0500,
+    GGL_INVALID_VALUE               = 0x0501,
+    GGL_INVALID_OPERATION           = 0x0502,
+    GGL_STACK_OVERFLOW              = 0x0503,
+    GGL_STACK_UNDERFLOW             = 0x0504,
+    GGL_OUT_OF_MEMORY               = 0x0505
+};
+
+// ----------------------------------------------------------------------------
+
+typedef struct {
+    GGLsizei    version;    // always set to sizeof(GGLSurface)
+    GGLuint     width;      // width in pixels
+    GGLuint     height;     // height in pixels
+    GGLint      stride;     // stride in pixels
+    GGLubyte*   data;       // pointer to the bits
+    GGLubyte    format;     // pixel format
+    GGLubyte    rfu[3];     // must be zero
+    // these values are dependent on the used format
+    union {
+        GGLint  compressedFormat;
+        GGLint  vstride;
+    };
+    void*       reserved;
+} GGLSurface;
+
+
+typedef struct {
+    // immediate rendering
+    void (*pointx)(void *con, const GGLcoord* v, GGLcoord r);
+    void (*linex)(void *con, 
+            const GGLcoord* v0, const GGLcoord* v1, GGLcoord width);
+    void (*recti)(void* c, GGLint l, GGLint t, GGLint r, GGLint b); 
+    void (*trianglex)(void* c,
+            GGLcoord const* v0, GGLcoord const* v1, GGLcoord const* v2);
+
+    // scissor
+    void (*scissor)(void* c, GGLint x, GGLint y, GGLsizei width, GGLsizei height);
+
+    // Set the textures and color buffers
+    void (*activeTexture)(void* c, GGLuint tmu);
+    void (*bindTexture)(void* c, const GGLSurface* surface);
+    void (*colorBuffer)(void* c, const GGLSurface* surface);
+    void (*readBuffer)(void* c, const GGLSurface* surface);
+    void (*depthBuffer)(void* c, const GGLSurface* surface);
+    void (*bindTextureLod)(void* c, GGLuint tmu, const GGLSurface* surface);
+
+    // enable/disable features
+    void (*enable)(void* c, GGLenum name);
+    void (*disable)(void* c, GGLenum name);
+    void (*enableDisable)(void* c, GGLenum name, GGLboolean en);
+
+    // specify the fragment's color
+    void (*shadeModel)(void* c, GGLenum mode);
+    void (*color4xv)(void* c, const GGLclampx* color);
+    // specify color iterators (16.16)
+    void (*colorGrad12xv)(void* c, const GGLcolor* grad);
+
+    // specify Z coordinate iterators (0.32)
+    void (*zGrad3xv)(void* c, const GGLfixed32* grad);
+
+    // specify W coordinate iterators (16.16)
+    void (*wGrad3xv)(void* c, const GGLfixed* grad);
+
+    // specify fog iterator & color (16.16)
+    void (*fogGrad3xv)(void* c, const GGLfixed* grad);
+    void (*fogColor3xv)(void* c, const GGLclampx* color);
+
+    // specify blending parameters
+    void (*blendFunc)(void* c, GGLenum src, GGLenum dst);
+    void (*blendFuncSeparate)(void* c,  GGLenum src, GGLenum dst,
+                                        GGLenum srcAlpha, GGLenum dstAplha);
+
+    // texture environnement (REPLACE / MODULATE / DECAL / BLEND)
+    void (*texEnvi)(void* c,    GGLenum target,
+                                GGLenum pname,
+                                GGLint param);
+
+    void (*texEnvxv)(void* c, GGLenum target,
+            GGLenum pname, const GGLfixed* params);
+
+    // texture parameters (Wrapping, filter)
+    void (*texParameteri)(void* c,  GGLenum target,
+                                    GGLenum pname,
+                                    GGLint param);
+
+    // texture iterators (16.16)
+    void (*texCoord2i)(void* c, GGLint s, GGLint t);
+    void (*texCoord2x)(void* c, GGLfixed s, GGLfixed t);
+    
+    // s, dsdx, dsdy, scale, t, dtdx, dtdy, tscale
+    // This api uses block floating-point for S and T texture coordinates.
+    // All values are given in 16.16, scaled by 'scale'. In other words,
+    // set scale to 0, for 16.16 values.
+    void (*texCoordGradScale8xv)(void* c, GGLint tmu, const int32_t* grad8);
+    
+    void (*texGeni)(void* c, GGLenum coord, GGLenum pname, GGLint param);
+
+    // masking
+    void (*colorMask)(void* c,  GGLboolean red,
+                                GGLboolean green,
+                                GGLboolean blue,
+                                GGLboolean alpha);
+
+    void (*depthMask)(void* c, GGLboolean flag);
+
+    void (*stencilMask)(void* c, GGLuint mask);
+
+    // alpha func
+    void (*alphaFuncx)(void* c, GGLenum func, GGLclampx ref);
+
+    // depth func
+    void (*depthFunc)(void* c, GGLenum func);
+
+    // logic op
+    void (*logicOp)(void* c, GGLenum opcode); 
+
+    // clear
+    void (*clear)(void* c, GGLbitfield mask);
+    void (*clearColorx)(void* c,
+            GGLclampx r, GGLclampx g, GGLclampx b, GGLclampx a);
+    void (*clearDepthx)(void* c, GGLclampx depth);
+    void (*clearStencil)(void* c, GGLint s);
+
+    // framebuffer operations
+    void (*copyPixels)(void* c, GGLint x, GGLint y,
+            GGLsizei width, GGLsizei height, GGLenum type);
+    void (*rasterPos2x)(void* c, GGLfixed x, GGLfixed y);
+    void (*rasterPos2i)(void* c, GGLint x, GGLint y);
+} GGLContext;
+
+// ----------------------------------------------------------------------------
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// construct / destroy the context
+ssize_t gglInit(GGLContext** context);
+ssize_t gglUninit(GGLContext* context);
+
+GGLint gglBitBlit(
+        GGLContext* c,
+        int tmu,
+        GGLint crop[4],
+        GGLint where[4]);
+
+#ifdef __cplusplus
+};
+#endif
+
+// ----------------------------------------------------------------------------
+
+#endif // ANDROID_PIXELFLINGER_H
diff --git a/package/utils/adbd/src/include/private/android_filesystem_capability.h b/package/utils/adbd/src/include/private/android_filesystem_capability.h
new file mode 100644
index 0000000..0505cda
--- /dev/null
+++ b/package/utils/adbd/src/include/private/android_filesystem_capability.h
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+/*
+ * Taken from linux/capability.h, with minor modifications
+ */
+
+#ifndef _SYSTEM_CORE_INCLUDE_PRIVATE_ANDROID_FILESYSTEM_CAPABILITY_H
+#define _SYSTEM_CORE_INCLUDE_PRIVATE_ANDROID_FILESYSTEM_CAPABILITY_H
+
+#include <stdint.h>
+
+#define __user
+#define __u32 uint32_t
+#define __le32 uint32_t
+
+#define _LINUX_CAPABILITY_VERSION_1 0x19980330
+#define _LINUX_CAPABILITY_U32S_1 1
+#define _LINUX_CAPABILITY_VERSION_2 0x20071026
+#define _LINUX_CAPABILITY_U32S_2 2
+#define _LINUX_CAPABILITY_VERSION_3 0x20080522
+#define _LINUX_CAPABILITY_U32S_3 2
+
+typedef struct __user_cap_header_struct {
+ __u32 version;
+ int pid;
+} __user *cap_user_header_t;
+
+typedef struct __user_cap_data_struct {
+ __u32 effective;
+ __u32 permitted;
+ __u32 inheritable;
+} __user *cap_user_data_t;
+
+#define VFS_CAP_REVISION_MASK 0xFF000000
+#define VFS_CAP_REVISION_SHIFT 24
+#define VFS_CAP_FLAGS_MASK ~VFS_CAP_REVISION_MASK
+#define VFS_CAP_FLAGS_EFFECTIVE 0x000001
+#define VFS_CAP_REVISION_1 0x01000000
+#define VFS_CAP_U32_1 1
+#define XATTR_CAPS_SZ_1 (sizeof(__le32)*(1 + 2*VFS_CAP_U32_1))
+#define VFS_CAP_REVISION_2 0x02000000
+#define VFS_CAP_U32_2 2
+#define XATTR_CAPS_SZ_2 (sizeof(__le32)*(1 + 2*VFS_CAP_U32_2))
+#define XATTR_CAPS_SZ XATTR_CAPS_SZ_2
+#define VFS_CAP_U32 VFS_CAP_U32_2
+#define VFS_CAP_REVISION VFS_CAP_REVISION_2
+
+struct vfs_cap_data {
+ __le32 magic_etc;
+ struct {
+ __le32 permitted;
+ __le32 inheritable;
+ } data[VFS_CAP_U32];
+};
+
+#define _LINUX_CAPABILITY_VERSION _LINUX_CAPABILITY_VERSION_1
+#define _LINUX_CAPABILITY_U32S _LINUX_CAPABILITY_U32S_1
+#define CAP_CHOWN 0
+#define CAP_DAC_OVERRIDE 1
+#define CAP_DAC_READ_SEARCH 2
+#define CAP_FOWNER 3
+#define CAP_FSETID 4
+#define CAP_KILL 5
+#define CAP_SETGID 6
+#define CAP_SETUID 7
+#define CAP_SETPCAP 8
+#define CAP_LINUX_IMMUTABLE 9
+#define CAP_NET_BIND_SERVICE 10
+#define CAP_NET_BROADCAST 11
+#define CAP_NET_ADMIN 12
+#define CAP_NET_RAW 13
+#define CAP_IPC_LOCK 14
+#define CAP_IPC_OWNER 15
+#define CAP_SYS_MODULE 16
+#define CAP_SYS_RAWIO 17
+#define CAP_SYS_CHROOT 18
+#define CAP_SYS_PTRACE 19
+#define CAP_SYS_PACCT 20
+#define CAP_SYS_ADMIN 21
+#define CAP_SYS_BOOT 22
+#define CAP_SYS_NICE 23
+#define CAP_SYS_RESOURCE 24
+#define CAP_SYS_TIME 25
+#define CAP_SYS_TTY_CONFIG 26
+#define CAP_MKNOD 27
+#define CAP_LEASE 28
+#define CAP_AUDIT_WRITE 29
+#define CAP_AUDIT_CONTROL 30
+#define CAP_SETFCAP 31
+#define CAP_MAC_OVERRIDE 32
+#define CAP_MAC_ADMIN 33
+#define CAP_SYSLOG 34
+#define CAP_WAKE_ALARM 35
+#define CAP_LAST_CAP CAP_WAKE_ALARM
+#define cap_valid(x) ((x) >= 0 && (x) <= CAP_LAST_CAP)
+#define CAP_TO_INDEX(x) ((x) >> 5)
+#define CAP_TO_MASK(x) (1 << ((x) & 31))
+
+#undef __user
+#undef __u32
+#undef __le32
+
+#endif
diff --git a/package/utils/adbd/src/include/private/android_filesystem_config.h b/package/utils/adbd/src/include/private/android_filesystem_config.h
new file mode 100644
index 0000000..06c9941
--- /dev/null
+++ b/package/utils/adbd/src/include/private/android_filesystem_config.h
@@ -0,0 +1,310 @@
+/*
+ * 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.
+ */
+
+/* This file is used to define the properties of the filesystem
+** images generated by build tools (mkbootfs and mkyaffs2image) and
+** by the device side of adb.
+*/
+
+#ifndef _ANDROID_FILESYSTEM_CONFIG_H_
+#define _ANDROID_FILESYSTEM_CONFIG_H_
+
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <stdint.h>
+
+//#ifdef HAVE_ANDROID_OS
+//#include <linux/capability.h>
+//#else
+//#include "android_filesystem_capability.h"
+//#endif
+
+/* This is the master Users and Groups config for the platform.
+ * DO NOT EVER RENUMBER
+ */
+
+#define AID_ROOT             0  /* traditional unix root user */
+
+#define AID_SYSTEM        1000  /* system server */
+
+#define AID_RADIO         1001  /* telephony subsystem, RIL */
+#define AID_BLUETOOTH     1002  /* bluetooth subsystem */
+#define AID_GRAPHICS      1003  /* graphics devices */
+#define AID_INPUT         1004  /* input devices */
+#define AID_AUDIO         1005  /* audio devices */
+#define AID_CAMERA        1006  /* camera devices */
+#define AID_LOG           1007  /* log devices */
+#define AID_COMPASS       1008  /* compass device */
+#define AID_MOUNT         1009  /* mountd socket */
+#define AID_WIFI          1010  /* wifi subsystem */
+#define AID_ADB           1011  /* android debug bridge (adbd) */
+#define AID_INSTALL       1012  /* group for installing packages */
+#define AID_MEDIA         1013  /* mediaserver process */
+#define AID_DHCP          1014  /* dhcp client */
+#define AID_SDCARD_RW     1015  /* external storage write access */
+#define AID_VPN           1016  /* vpn system */
+#define AID_KEYSTORE      1017  /* keystore subsystem */
+#define AID_USB           1018  /* USB devices */
+#define AID_DRM           1019  /* DRM server */
+#define AID_MDNSR         1020  /* MulticastDNSResponder (service discovery) */
+#define AID_GPS           1021  /* GPS daemon */
+#define AID_UNUSED1       1022  /* deprecated, DO NOT USE */
+#define AID_MEDIA_RW      1023  /* internal media storage write access */
+#define AID_MTP           1024  /* MTP USB driver access */
+#define AID_UNUSED2       1025  /* deprecated, DO NOT USE */
+#define AID_DRMRPC        1026  /* group for drm rpc */
+#define AID_NFC           1027  /* nfc subsystem */
+#define AID_SDCARD_R      1028  /* external storage read access */
+#define AID_CLAT          1029  /* clat part of nat464 */
+#define AID_LOOP_RADIO    1030  /* loop radio devices */
+#define AID_MEDIA_DRM     1031  /* MediaDrm plugins */
+#define AID_PACKAGE_INFO  1032  /* access to installed package details */
+#define AID_SDCARD_PICS   1033  /* external storage photos access */
+#define AID_SDCARD_AV     1034  /* external storage audio/video access */
+#define AID_SDCARD_ALL    1035  /* access all users external storage */
+#define AID_LOGD          1036  /* log daemon */
+#define AID_SHARED_RELRO  1037  /* creator of shared GNU RELRO files */
+
+#define AID_SHELL         2000  /* adb and debug shell user */
+#define AID_CACHE         2001  /* cache access */
+#define AID_DIAG          2002  /* access to diagnostic resources */
+
+/* The 3000 series are intended for use as supplemental group id's only.
+ * They indicate special Android capabilities that the kernel is aware of. */
+#define AID_NET_BT_ADMIN  3001  /* bluetooth: create any socket */
+#define AID_NET_BT        3002  /* bluetooth: create sco, rfcomm or l2cap sockets */
+#define AID_INET          3003  /* can create AF_INET and AF_INET6 sockets */
+#define AID_NET_RAW       3004  /* can create raw INET sockets */
+#define AID_NET_ADMIN     3005  /* can configure interfaces and routing tables. */
+#define AID_NET_BW_STATS  3006  /* read bandwidth statistics */
+#define AID_NET_BW_ACCT   3007  /* change bandwidth statistics accounting */
+#define AID_NET_BT_STACK  3008  /* bluetooth: access config files */
+
+#define AID_EVERYBODY     9997  /* shared between all apps in the same profile */
+#define AID_MISC          9998  /* access to misc storage */
+#define AID_NOBODY        9999
+
+#define AID_APP          10000  /* first app user */
+
+#define AID_ISOLATED_START 99000 /* start of uids for fully isolated sandboxed processes */
+#define AID_ISOLATED_END   99999 /* end of uids for fully isolated sandboxed processes */
+
+#define AID_USER        100000  /* offset for uid ranges for each user */
+
+#define AID_SHARED_GID_START 50000 /* start of gids for apps in each user to share */
+#define AID_SHARED_GID_END   59999 /* start of gids for apps in each user to share */
+
+#if !defined(EXCLUDE_FS_CONFIG_STRUCTURES)
+struct android_id_info {
+    const char *name;
+    unsigned aid;
+};
+
+static const struct android_id_info android_ids[] = {
+    { "root",          AID_ROOT, },
+
+    { "system",        AID_SYSTEM, },
+
+    { "radio",         AID_RADIO, },
+    { "bluetooth",     AID_BLUETOOTH, },
+    { "graphics",      AID_GRAPHICS, },
+    { "input",         AID_INPUT, },
+    { "audio",         AID_AUDIO, },
+    { "camera",        AID_CAMERA, },
+    { "log",           AID_LOG, },
+    { "compass",       AID_COMPASS, },
+    { "mount",         AID_MOUNT, },
+    { "wifi",          AID_WIFI, },
+    { "adb",           AID_ADB, },
+    { "install",       AID_INSTALL, },
+    { "media",         AID_MEDIA, },
+    { "dhcp",          AID_DHCP, },
+    { "sdcard_rw",     AID_SDCARD_RW, },
+    { "vpn",           AID_VPN, },
+    { "keystore",      AID_KEYSTORE, },
+    { "usb",           AID_USB, },
+    { "drm",           AID_DRM, },
+    { "mdnsr",         AID_MDNSR, },
+    { "gps",           AID_GPS, },
+    // AID_UNUSED1
+    { "media_rw",      AID_MEDIA_RW, },
+    { "mtp",           AID_MTP, },
+    // AID_UNUSED2
+    { "drmrpc",        AID_DRMRPC, },
+    { "nfc",           AID_NFC, },
+    { "sdcard_r",      AID_SDCARD_R, },
+    { "clat",          AID_CLAT, },
+    { "loop_radio",    AID_LOOP_RADIO, },
+    { "mediadrm",      AID_MEDIA_DRM, },
+    { "package_info",  AID_PACKAGE_INFO, },
+    { "sdcard_pics",   AID_SDCARD_PICS, },
+    { "sdcard_av",     AID_SDCARD_AV, },
+    { "sdcard_all",    AID_SDCARD_ALL, },
+    { "logd",          AID_LOGD, },
+    { "shared_relro",  AID_SHARED_RELRO, },
+
+    { "shell",         AID_SHELL, },
+    { "cache",         AID_CACHE, },
+    { "diag",          AID_DIAG, },
+
+    { "net_bt_admin",  AID_NET_BT_ADMIN, },
+    { "net_bt",        AID_NET_BT, },
+    { "inet",          AID_INET, },
+    { "net_raw",       AID_NET_RAW, },
+    { "net_admin",     AID_NET_ADMIN, },
+    { "net_bw_stats",  AID_NET_BW_STATS, },
+    { "net_bw_acct",   AID_NET_BW_ACCT, },
+    { "net_bt_stack",  AID_NET_BT_STACK, },
+
+    { "everybody",     AID_EVERYBODY, },
+    { "misc",          AID_MISC, },
+    { "nobody",        AID_NOBODY, },
+};
+
+#define android_id_count \
+    (sizeof(android_ids) / sizeof(android_ids[0]))
+
+struct fs_path_config {
+    unsigned mode;
+    unsigned uid;
+    unsigned gid;
+    uint64_t capabilities;
+    const char *prefix;
+};
+
+/* Rules for directories.
+** These rules are applied based on "first match", so they
+** should start with the most specific path and work their
+** way up to the root.
+*/
+
+static const struct fs_path_config android_dirs[] = {
+    { 00770, AID_SYSTEM, AID_CACHE,  0, "cache" },
+    { 00771, AID_SYSTEM, AID_SYSTEM, 0, "data/app" },
+    { 00771, AID_SYSTEM, AID_SYSTEM, 0, "data/app-private" },
+    { 00771, AID_SYSTEM, AID_SYSTEM, 0, "data/dalvik-cache" },
+    { 00771, AID_SYSTEM, AID_SYSTEM, 0, "data/data" },
+    { 00771, AID_SHELL,  AID_SHELL,  0, "data/local/tmp" },
+    { 00771, AID_SHELL,  AID_SHELL,  0, "data/local" },
+    { 01771, AID_SYSTEM, AID_MISC,   0, "data/misc" },
+    { 00770, AID_DHCP,   AID_DHCP,   0, "data/misc/dhcp" },
+    { 00771, AID_SHARED_RELRO, AID_SHARED_RELRO, 0, "data/misc/shared_relro" },
+    { 00775, AID_MEDIA_RW, AID_MEDIA_RW, 0, "data/media" },
+    { 00775, AID_MEDIA_RW, AID_MEDIA_RW, 0, "data/media/Music" },
+    { 00771, AID_SYSTEM, AID_SYSTEM, 0, "data" },
+    { 00750, AID_ROOT,   AID_SHELL,  0, "sbin" },
+    { 00755, AID_ROOT,   AID_SHELL,  0, "system/bin" },
+    { 00755, AID_ROOT,   AID_SHELL,  0, "system/vendor" },
+    { 00755, AID_ROOT,   AID_SHELL,  0, "system/xbin" },
+    { 00755, AID_ROOT,   AID_ROOT,   0, "system/etc/ppp" },
+    { 00755, AID_ROOT,   AID_SHELL,  0, "vendor" },
+    { 00777, AID_ROOT,   AID_ROOT,   0, "sdcard" },
+    { 00755, AID_ROOT,   AID_ROOT,   0, 0 },
+};
+
+/* Rules for files.
+** These rules are applied based on "first match", so they
+** should start with the most specific path and work their
+** way up to the root. Prefixes ending in * denotes wildcard
+** and will allow partial matches.
+*/
+static const struct fs_path_config android_files[] = {
+    { 00440, AID_ROOT,      AID_SHELL,     0, "system/etc/init.goldfish.rc" },
+    { 00550, AID_ROOT,      AID_SHELL,     0, "system/etc/init.goldfish.sh" },
+    { 00440, AID_ROOT,      AID_SHELL,     0, "system/etc/init.trout.rc" },
+    { 00550, AID_ROOT,      AID_SHELL,     0, "system/etc/init.ril" },
+    { 00550, AID_ROOT,      AID_SHELL,     0, "system/etc/init.testmenu" },
+    { 00550, AID_DHCP,      AID_SHELL,     0, "system/etc/dhcpcd/dhcpcd-run-hooks" },
+    { 00444, AID_RADIO,     AID_AUDIO,     0, "system/etc/AudioPara4.csv" },
+    { 00555, AID_ROOT,      AID_ROOT,      0, "system/etc/ppp/*" },
+    { 00555, AID_ROOT,      AID_ROOT,      0, "system/etc/rc.*" },
+    { 00644, AID_SYSTEM,    AID_SYSTEM,    0, "data/app/*" },
+    { 00644, AID_MEDIA_RW,  AID_MEDIA_RW,  0, "data/media/*" },
+    { 00644, AID_SYSTEM,    AID_SYSTEM,    0, "data/app-private/*" },
+    { 00644, AID_APP,       AID_APP,       0, "data/data/*" },
+    { 00755, AID_ROOT,      AID_ROOT,      0, "system/bin/ping" },
+
+    /* the following file is INTENTIONALLY set-gid and not set-uid.
+     * Do not change. */
+    { 02750, AID_ROOT,      AID_INET,      0, "system/bin/netcfg" },
+
+    /* the following five files are INTENTIONALLY set-uid, but they
+     * are NOT included on user builds. */
+    { 04750, AID_ROOT,      AID_SHELL,     0, "system/xbin/su" },
+    { 06755, AID_ROOT,      AID_ROOT,      0, "system/xbin/librank" },
+    { 06755, AID_ROOT,      AID_ROOT,      0, "system/xbin/procrank" },
+    { 06755, AID_ROOT,      AID_ROOT,      0, "system/xbin/procmem" },
+    { 06755, AID_ROOT,      AID_ROOT,      0, "system/xbin/tcpdump" },
+    { 04770, AID_ROOT,      AID_RADIO,     0, "system/bin/pppd-ril" },
+
+    /* the following files have enhanced capabilities and ARE included in user builds. */
+    { 00750, AID_ROOT,      AID_SHELL,     0, "system/bin/run-as" },
+
+    { 00750, AID_ROOT,      AID_ROOT,      0, "system/bin/uncrypt" },
+    { 00750, AID_ROOT,      AID_ROOT,      0, "system/bin/install-recovery.sh" },
+    { 00755, AID_ROOT,      AID_SHELL,     0, "system/bin/*" },
+    { 00755, AID_ROOT,      AID_ROOT,      0, "system/lib/valgrind/*" },
+    { 00755, AID_ROOT,      AID_ROOT,      0, "system/lib64/valgrind/*" },
+    { 00755, AID_ROOT,      AID_SHELL,     0, "system/xbin/*" },
+    { 00755, AID_ROOT,      AID_SHELL,     0, "system/vendor/bin/*" },
+    { 00755, AID_ROOT,      AID_SHELL,     0, "vendor/bin/*" },
+    { 00750, AID_ROOT,      AID_SHELL,     0, "sbin/*" },
+    { 00755, AID_ROOT,      AID_ROOT,      0, "bin/*" },
+    { 00750, AID_ROOT,      AID_SHELL,     0, "init*" },
+    { 00750, AID_ROOT,      AID_SHELL,     0, "sbin/fs_mgr" },
+    { 00640, AID_ROOT,      AID_SHELL,     0, "fstab.*" },
+    { 00644, AID_ROOT,      AID_ROOT,      0, 0 },
+};
+
+static inline void fs_config(const char *path, int dir,
+                             unsigned *uid, unsigned *gid, unsigned *mode, uint64_t *capabilities)
+{
+    const struct fs_path_config *pc;
+    int plen;
+
+    if (path[0] == '/') {
+        path++;
+    }
+
+    pc = dir ? android_dirs : android_files;
+    plen = strlen(path);
+    for(; pc->prefix; pc++){
+        int len = strlen(pc->prefix);
+        if (dir) {
+            if(plen < len) continue;
+            if(!strncmp(pc->prefix, path, len)) break;
+            continue;
+        }
+        /* If name ends in * then allow partial matches. */
+        if (pc->prefix[len -1] == '*') {
+            if(!strncmp(pc->prefix, path, len - 1)) break;
+        } else if (plen == len){
+            if(!strncmp(pc->prefix, path, len)) break;
+        }
+    }
+    *uid = pc->uid;
+    *gid = pc->gid;
+    *mode = (*mode & (~07777)) | pc->mode;
+    *capabilities = pc->capabilities;
+
+#if 0
+    fprintf(stderr,"< '%s' '%s' %d %d %o >\n",
+            path, pc->prefix ? pc->prefix : "", *uid, *gid, *mode);
+#endif
+}
+#endif
+#endif
diff --git a/package/utils/adbd/src/include/private/pixelflinger/ggl_context.h b/package/utils/adbd/src/include/private/pixelflinger/ggl_context.h
new file mode 100644
index 0000000..d43655c
--- /dev/null
+++ b/package/utils/adbd/src/include/private/pixelflinger/ggl_context.h
@@ -0,0 +1,565 @@
+/*
+ * 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 ANDROID_GGL_CONTEXT_H
+#define ANDROID_GGL_CONTEXT_H
+
+#include <stdint.h>
+#include <stddef.h>
+#include <string.h>
+#include <sys/types.h>
+#include <endian.h>
+
+#include <pixelflinger/pixelflinger.h>
+#include <private/pixelflinger/ggl_fixed.h>
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+
+inline uint32_t GGL_RGBA_TO_HOST(uint32_t v) {
+    return v;
+}
+inline uint32_t GGL_HOST_TO_RGBA(uint32_t v) {
+    return v;
+}
+
+#else
+
+inline uint32_t GGL_RGBA_TO_HOST(uint32_t v) {
+#if defined(__mips__) && __mips==32 && __mips_isa_rev>=2
+    uint32_t r;
+    __asm__("wsbh %0, %1;"
+        "rotr %0, %0, 16"
+        : "=r" (r)
+        : "r" (v)
+        );
+    return r;
+#else
+    return (v<<24) | (v>>24) | ((v<<8)&0xff0000) | ((v>>8)&0xff00);
+#endif
+}
+inline uint32_t GGL_HOST_TO_RGBA(uint32_t v) {
+#if defined(__mips__) && __mips==32 && __mips_isa_rev>=2
+    uint32_t r;
+    __asm__("wsbh %0, %1;"
+        "rotr %0, %0, 16"
+        : "=r" (r)
+        : "r" (v)
+        );
+    return r;
+#else
+    return (v<<24) | (v>>24) | ((v<<8)&0xff0000) | ((v>>8)&0xff00);
+#endif
+}
+
+#endif
+
+// ----------------------------------------------------------------------------
+
+const int GGL_DITHER_BITS = 6;  // dither weights stored on 6 bits
+const int GGL_DITHER_ORDER_SHIFT= 3;
+const int GGL_DITHER_ORDER      = (1<<GGL_DITHER_ORDER_SHIFT);
+const int GGL_DITHER_SIZE       = GGL_DITHER_ORDER * GGL_DITHER_ORDER;
+const int GGL_DITHER_MASK       = GGL_DITHER_ORDER-1;
+
+// ----------------------------------------------------------------------------
+
+const int GGL_SUBPIXEL_BITS = 4;
+
+// TRI_FRACTION_BITS defines the number of bits we want to use
+// for the sub-pixel coordinates during the edge stepping, the
+// value shouldn't be more than 7, or bad things are going to
+// happen when drawing large triangles (8 doesn't work because
+// 32 bit muls will loose the sign bit)
+
+#define  TRI_FRACTION_BITS  (GGL_SUBPIXEL_BITS)
+#define  TRI_ONE            (1 << TRI_FRACTION_BITS)
+#define  TRI_HALF           (1 << (TRI_FRACTION_BITS-1))
+#define  TRI_FROM_INT(x)    ((x) << TRI_FRACTION_BITS)
+#define  TRI_FRAC(x)        ((x)                 &  (TRI_ONE-1))
+#define  TRI_FLOOR(x)       ((x)                 & ~(TRI_ONE-1))
+#define  TRI_CEIL(x)        (((x) + (TRI_ONE-1)) & ~(TRI_ONE-1))
+#define  TRI_ROUND(x)       (((x) +  TRI_HALF  ) & ~(TRI_ONE-1))
+
+#define  TRI_ROUDNING       (1 << (16 - TRI_FRACTION_BITS - 1))
+#define  TRI_FROM_FIXED(x)  (((x)+TRI_ROUDNING) >> (16-TRI_FRACTION_BITS))
+
+#define  TRI_SNAP_NEXT_HALF(x)   (TRI_CEIL((x)+TRI_HALF) - TRI_HALF)
+#define  TRI_SNAP_PREV_HALF(x)   (TRI_CEIL((x)-TRI_HALF) - TRI_HALF)
+
+// ----------------------------------------------------------------------------
+
+const int GGL_COLOR_BITS = 24;
+
+// To maintain 8-bits color chanels, with a maximum GGLSurface
+// size of 4096 and GGL_SUBPIXEL_BITS=4, we need 8 + 12 + 4 = 24 bits
+// for encoding the color iterators
+
+inline GGLcolor gglFixedToIteratedColor(GGLfixed c) {
+    return (c << 8) - c;
+}
+
+// ----------------------------------------------------------------------------
+
+template<bool> struct CTA;
+template<> struct CTA<true> { };
+
+#define GGL_CONTEXT(con, c)         context_t *con = static_cast<context_t *>(c)
+#define GGL_OFFSETOF(field)         uintptr_t(&(((context_t*)0)->field))
+#define GGL_INIT_PROC(p, f)         p.f = ggl_ ## f;
+#define GGL_BETWEEN(x, L, H)        (uint32_t((x)-(L)) <= ((H)-(L)))
+
+#define ggl_likely(x)	__builtin_expect(!!(x), 1)
+#define ggl_unlikely(x)	__builtin_expect(!!(x), 0)
+
+const int GGL_TEXTURE_UNIT_COUNT    = 2;
+const int GGL_TMU_STATE             = 0x00000001;
+const int GGL_CB_STATE              = 0x00000002;
+const int GGL_PIXEL_PIPELINE_STATE  = 0x00000004;
+
+// ----------------------------------------------------------------------------
+
+#define GGL_RESERVE_NEEDS(name, l, s)                               \
+    const uint32_t  GGL_NEEDS_##name##_MASK = (((1LU<<(s))-1)<<l);  \
+    const uint32_t  GGL_NEEDS_##name##_SHIFT = (l);
+
+#define GGL_BUILD_NEEDS(val, name)                                  \
+    (((val)<<(GGL_NEEDS_##name##_SHIFT)) & GGL_NEEDS_##name##_MASK)
+
+#define GGL_READ_NEEDS(name, n)                                     \
+    (uint32_t(n & GGL_NEEDS_##name##_MASK) >> GGL_NEEDS_##name##_SHIFT)
+
+#define GGL_NEED_MASK(name)     (uint32_t(GGL_NEEDS_##name##_MASK))
+#define GGL_NEED(name, val)     GGL_BUILD_NEEDS(val, name)
+
+GGL_RESERVE_NEEDS( CB_FORMAT,       0, 6 )
+GGL_RESERVE_NEEDS( SHADE,           6, 1 )
+GGL_RESERVE_NEEDS( W,               7, 1 )
+GGL_RESERVE_NEEDS( BLEND_SRC,       8, 4 )
+GGL_RESERVE_NEEDS( BLEND_DST,      12, 4 )
+GGL_RESERVE_NEEDS( BLEND_SRCA,     16, 4 )
+GGL_RESERVE_NEEDS( BLEND_DSTA,     20, 4 )
+GGL_RESERVE_NEEDS( LOGIC_OP,       24, 4 )
+GGL_RESERVE_NEEDS( MASK_ARGB,      28, 4 )
+
+GGL_RESERVE_NEEDS( P_ALPHA_TEST,    0, 3 )
+GGL_RESERVE_NEEDS( P_AA,            3, 1 )
+GGL_RESERVE_NEEDS( P_DEPTH_TEST,    4, 3 )
+GGL_RESERVE_NEEDS( P_MASK_Z,        7, 1 )
+GGL_RESERVE_NEEDS( P_DITHER,        8, 1 )
+GGL_RESERVE_NEEDS( P_FOG,           9, 1 )
+GGL_RESERVE_NEEDS( P_RESERVED1,    10,22 )
+
+GGL_RESERVE_NEEDS( T_FORMAT,        0, 6 )
+GGL_RESERVE_NEEDS( T_RESERVED0,     6, 1 )
+GGL_RESERVE_NEEDS( T_POT,           7, 1 )
+GGL_RESERVE_NEEDS( T_S_WRAP,        8, 2 )
+GGL_RESERVE_NEEDS( T_T_WRAP,       10, 2 )
+GGL_RESERVE_NEEDS( T_ENV,          12, 3 )
+GGL_RESERVE_NEEDS( T_LINEAR,       15, 1 )
+
+const int GGL_NEEDS_WRAP_CLAMP_TO_EDGE  = 0;
+const int GGL_NEEDS_WRAP_REPEAT         = 1;
+const int GGL_NEEDS_WRAP_11             = 2;
+
+inline uint32_t ggl_wrap_to_needs(uint32_t e) {
+    switch (e) {
+    case GGL_CLAMP:         return GGL_NEEDS_WRAP_CLAMP_TO_EDGE;
+    case GGL_REPEAT:        return GGL_NEEDS_WRAP_REPEAT;
+    }
+    return 0;
+}
+
+inline uint32_t ggl_blendfactor_to_needs(uint32_t b) {
+    if (b <= 1) return b;
+    return (b & 0xF)+2;
+}
+
+inline uint32_t ggl_needs_to_blendfactor(uint32_t n) {
+    if (n <= 1) return n;
+    return (n - 2) + 0x300;
+}
+
+inline uint32_t ggl_env_to_needs(uint32_t e) {
+    switch (e) {
+    case GGL_REPLACE:   return 0;
+    case GGL_MODULATE:  return 1;
+    case GGL_DECAL:     return 2;
+    case GGL_BLEND:     return 3;
+    case GGL_ADD:       return 4;
+    }
+    return 0;
+}
+
+inline uint32_t ggl_needs_to_env(uint32_t n) {
+    const uint32_t envs[] = { GGL_REPLACE, GGL_MODULATE, 
+            GGL_DECAL, GGL_BLEND, GGL_ADD };
+    return envs[n];
+
+}
+
+// ----------------------------------------------------------------------------
+
+enum {
+    GGL_ENABLE_BLENDING     = 0x00000001,
+    GGL_ENABLE_SMOOTH       = 0x00000002,
+    GGL_ENABLE_AA           = 0x00000004,
+    GGL_ENABLE_LOGIC_OP     = 0x00000008,
+    GGL_ENABLE_ALPHA_TEST   = 0x00000010,
+    GGL_ENABLE_SCISSOR_TEST = 0x00000020,
+    GGL_ENABLE_TMUS         = 0x00000040,
+    GGL_ENABLE_DEPTH_TEST   = 0x00000080,
+    GGL_ENABLE_STENCIL_TEST = 0x00000100,
+    GGL_ENABLE_W            = 0x00000200,
+    GGL_ENABLE_DITHER       = 0x00000400,
+    GGL_ENABLE_FOG          = 0x00000800,
+    GGL_ENABLE_POINT_AA_NICE= 0x00001000
+};
+
+// ----------------------------------------------------------------------------
+
+class needs_filter_t;
+struct needs_t {
+    inline int match(const needs_filter_t& filter);
+    inline bool operator == (const needs_t& rhs) const {
+        return  (n==rhs.n) &&
+                (p==rhs.p) &&
+                (t[0]==rhs.t[0]) &&
+                (t[1]==rhs.t[1]);
+    }
+    inline bool operator != (const needs_t& rhs) const {
+        return !operator == (rhs);
+    }
+    uint32_t    n;
+    uint32_t    p;
+    uint32_t    t[GGL_TEXTURE_UNIT_COUNT];
+};
+
+inline int compare_type(const needs_t& lhs, const needs_t& rhs) {
+    return memcmp(&lhs, &rhs, sizeof(needs_t));
+}
+
+struct needs_filter_t {
+    needs_t     value;
+    needs_t     mask;
+};
+
+int needs_t::match(const needs_filter_t& filter) {
+    uint32_t result = 
+        ((filter.value.n ^ n)       & filter.mask.n)    |
+        ((filter.value.p ^ p)       & filter.mask.p)    |
+        ((filter.value.t[0] ^ t[0]) & filter.mask.t[0]) |
+        ((filter.value.t[1] ^ t[1]) & filter.mask.t[1]);
+    return (result == 0);
+}
+
+// ----------------------------------------------------------------------------
+
+struct context_t;
+class Assembly;
+
+struct blend_state_t {
+	uint32_t			src;
+	uint32_t			dst;
+	uint32_t			src_alpha;
+	uint32_t			dst_alpha;
+	uint8_t				reserved;
+	uint8_t				alpha_separate;
+	uint8_t				operation;
+	uint8_t				equation;
+};
+
+struct mask_state_t {
+    uint8_t             color;
+    uint8_t             depth;
+    uint32_t            stencil;
+};
+
+struct clear_state_t {
+    GGLclampx           r;
+    GGLclampx           g;
+    GGLclampx           b;
+    GGLclampx           a;
+    GGLclampx           depth;
+    GGLint              stencil;
+    uint32_t            colorPacked;
+    uint32_t            depthPacked;
+    uint32_t            stencilPacked;
+    uint32_t            dirty;
+};
+
+struct fog_state_t {
+    uint8_t     color[4];
+};
+
+struct logic_op_state_t {
+    uint16_t            opcode;
+};
+
+struct alpha_test_state_t {
+    uint16_t            func;
+    GGLcolor            ref;
+};
+
+struct depth_test_state_t {
+    uint16_t            func;
+    GGLclampx           clearValue;
+};
+
+struct scissor_t {
+    uint32_t            user_left;
+    uint32_t            user_right;
+    uint32_t            user_top;
+    uint32_t            user_bottom;
+    uint32_t            left;
+    uint32_t            right;
+    uint32_t            top;
+    uint32_t            bottom;
+};
+
+struct pixel_t {
+    uint32_t    c[4];
+    uint8_t     s[4];
+};
+
+struct surface_t {
+    union {
+        GGLSurface          s;
+        // Keep the following struct field types in line with the corresponding
+        // GGLSurface fields to avoid mismatches leading to errors.
+        struct {
+            GGLsizei        reserved;
+            GGLuint         width;
+            GGLuint         height;
+            GGLint          stride;
+            GGLubyte*       data;
+            GGLubyte        format;
+            GGLubyte        dirty;
+            GGLubyte        pad[2];
+        };
+    };
+    void                (*read) (const surface_t* s, context_t* c,
+                                uint32_t x, uint32_t y, pixel_t* pixel);
+    void                (*write)(const surface_t* s, context_t* c,
+                                uint32_t x, uint32_t y, const pixel_t* pixel);
+};
+
+// ----------------------------------------------------------------------------
+
+struct texture_shade_t {
+    union {
+        struct {
+            int32_t             is0;
+            int32_t             idsdx;
+            int32_t             idsdy;
+            int                 sscale;
+            int32_t             it0;
+            int32_t             idtdx;
+            int32_t             idtdy;
+            int                 tscale;
+        };
+        struct {
+            int32_t             v;
+            int32_t             dx;
+            int32_t             dy;
+            int                 scale;
+        } st[2];
+    };
+};
+
+struct texture_iterators_t {
+    // these are not encoded in the same way than in the
+    // texture_shade_t structure
+    union {
+        struct {
+            GGLfixed			ydsdy;
+            GGLfixed            dsdx;
+            GGLfixed            dsdy;
+            int                 sscale;
+            GGLfixed			ydtdy;
+            GGLfixed            dtdx;
+            GGLfixed            dtdy;
+            int                 tscale;
+        };
+        struct {
+            GGLfixed			ydvdy;
+            GGLfixed            dvdx;
+            GGLfixed            dvdy;
+            int                 scale;
+        } st[2];
+    };
+};
+
+struct texture_t {
+	surface_t			surface;
+	texture_iterators_t	iterators;
+    texture_shade_t     shade;
+	uint32_t			s_coord;
+	uint32_t            t_coord;
+	uint16_t			s_wrap;
+	uint16_t            t_wrap;
+	uint16_t            min_filter;
+	uint16_t            mag_filter;
+    uint16_t            env;
+    uint8_t             env_color[4];
+	uint8_t				enable;
+	uint8_t				dirty;
+};
+
+struct raster_t {
+    GGLfixed            x;
+    GGLfixed            y;
+};
+
+struct framebuffer_t {
+    surface_t           color;
+    surface_t           read;
+	surface_t			depth;
+	surface_t			stencil;
+    int16_t             *coverage;
+    size_t              coverageBufferSize;
+};
+
+// ----------------------------------------------------------------------------
+
+struct iterators_t {
+	int32_t             xl;
+	int32_t             xr;
+    int32_t             y;
+	GGLcolor			ydady;
+	GGLcolor			ydrdy;
+	GGLcolor			ydgdy;
+	GGLcolor			ydbdy;
+	GGLfixed			ydzdy;
+	GGLfixed			ydwdy;
+	GGLfixed			ydfdy;
+};
+
+struct shade_t {
+	GGLcolor			a0;
+    GGLcolor            dadx;
+    GGLcolor            dady;
+	GGLcolor			r0;
+    GGLcolor            drdx;
+    GGLcolor            drdy;
+	GGLcolor			g0;
+    GGLcolor            dgdx;
+    GGLcolor            dgdy;
+	GGLcolor			b0;
+    GGLcolor            dbdx;
+    GGLcolor            dbdy;
+	uint32_t            z0;
+    GGLfixed32          dzdx;
+    GGLfixed32          dzdy;
+	GGLfixed            w0;
+    GGLfixed            dwdx;
+    GGLfixed            dwdy;
+	uint32_t			f0;
+    GGLfixed            dfdx;
+    GGLfixed            dfdy;
+};
+
+// these are used in the generated code
+// we use this mirror structure to improve
+// data locality in the pixel pipeline
+struct generated_tex_vars_t {
+    uint32_t    width;
+    uint32_t    height;
+    uint32_t    stride;
+    uintptr_t   data;
+    int32_t     dsdx;
+    int32_t     dtdx;
+    int32_t     spill[2];
+};
+
+struct generated_vars_t {
+    struct {
+        int32_t c;
+        int32_t dx;
+    } argb[4];
+    int32_t     aref;
+    int32_t     dzdx;
+    int32_t     zbase;
+    int32_t     f;
+    int32_t     dfdx;
+    int32_t     spill[3];
+    generated_tex_vars_t    texture[GGL_TEXTURE_UNIT_COUNT];
+    int32_t     rt;
+    int32_t     lb;
+};
+
+// ----------------------------------------------------------------------------
+
+struct state_t {
+	framebuffer_t		buffers;
+	texture_t			texture[GGL_TEXTURE_UNIT_COUNT];
+    scissor_t           scissor;
+    raster_t            raster;
+	blend_state_t		blend;
+    alpha_test_state_t  alpha_test;
+    depth_test_state_t  depth_test;
+    mask_state_t        mask;
+    clear_state_t       clear;
+    fog_state_t         fog;
+    logic_op_state_t    logic_op;
+    uint32_t            enables;
+    uint32_t            enabled_tmu;
+    needs_t             needs;
+};
+
+// ----------------------------------------------------------------------------
+
+struct context_t {
+	GGLContext          procs;
+	state_t             state;
+    shade_t             shade;
+	iterators_t         iterators;
+    generated_vars_t    generated_vars                __attribute__((aligned(32)));
+    uint8_t             ditherMatrix[GGL_DITHER_SIZE] __attribute__((aligned(32)));
+    uint32_t            packed;
+    uint32_t            packed8888;
+    const GGLFormat*    formats;
+    uint32_t            dirty;
+    texture_t*          activeTMU;
+    uint32_t            activeTMUIndex;
+
+    void                (*init_y)(context_t* c, int32_t y);
+	void                (*step_y)(context_t* c);
+	void                (*scanline)(context_t* c);
+    void                (*span)(context_t* c);
+    void                (*rect)(context_t* c, size_t yc);
+    
+    void*               base;
+    Assembly*           scanline_as;
+    GGLenum             error;
+};
+
+// ----------------------------------------------------------------------------
+
+void ggl_init_context(context_t* context);
+void ggl_uninit_context(context_t* context);
+void ggl_error(context_t* c, GGLenum error);
+int64_t ggl_system_time();
+
+// ----------------------------------------------------------------------------
+
+};
+
+#endif // ANDROID_GGL_CONTEXT_H
+
diff --git a/package/utils/adbd/src/include/private/pixelflinger/ggl_fixed.h b/package/utils/adbd/src/include/private/pixelflinger/ggl_fixed.h
new file mode 100644
index 0000000..d0493f3
--- /dev/null
+++ b/package/utils/adbd/src/include/private/pixelflinger/ggl_fixed.h
@@ -0,0 +1,633 @@
+/*
+ * Copyright (C) 2005 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 ANDROID_GGL_FIXED_H
+#define ANDROID_GGL_FIXED_H
+
+#include <math.h>
+#include <pixelflinger/pixelflinger.h>
+
+// ----------------------------------------------------------------------------
+
+#define CONST           __attribute__((const))
+#define ALWAYS_INLINE   __attribute__((always_inline))
+
+const GGLfixed FIXED_BITS = 16;
+const GGLfixed FIXED_EPSILON  = 1;
+const GGLfixed FIXED_ONE  = 1L<<FIXED_BITS;
+const GGLfixed FIXED_HALF = 1L<<(FIXED_BITS-1);
+const GGLfixed FIXED_MIN  = 0x80000000L;
+const GGLfixed FIXED_MAX  = 0x7FFFFFFFL;
+
+inline GGLfixed gglIntToFixed(GGLfixed i)       ALWAYS_INLINE ;
+inline GGLfixed gglFixedToIntRound(GGLfixed f)  ALWAYS_INLINE ;
+inline GGLfixed gglFixedToIntFloor(GGLfixed f)  ALWAYS_INLINE ;
+inline GGLfixed gglFixedToIntCeil(GGLfixed f)   ALWAYS_INLINE ;
+inline GGLfixed gglFracx(GGLfixed v)            ALWAYS_INLINE ;
+inline GGLfixed gglFloorx(GGLfixed v)           ALWAYS_INLINE ;
+inline GGLfixed gglCeilx(GGLfixed v)            ALWAYS_INLINE ;
+inline GGLfixed gglCenterx(GGLfixed v)          ALWAYS_INLINE ;
+inline GGLfixed gglRoundx(GGLfixed v)           ALWAYS_INLINE ;
+
+GGLfixed gglIntToFixed(GGLfixed i) {
+    return i<<FIXED_BITS;
+}
+GGLfixed gglFixedToIntRound(GGLfixed f) {
+    return (f + FIXED_HALF)>>FIXED_BITS;
+}
+GGLfixed gglFixedToIntFloor(GGLfixed f) {
+    return f>>FIXED_BITS;
+}
+GGLfixed gglFixedToIntCeil(GGLfixed f) {
+    return (f + ((1<<FIXED_BITS) - 1))>>FIXED_BITS;
+}
+
+GGLfixed gglFracx(GGLfixed v) {
+    return v & ((1<<FIXED_BITS)-1);
+}
+GGLfixed gglFloorx(GGLfixed v) {
+    return gglFixedToIntFloor(v)<<FIXED_BITS;
+}
+GGLfixed gglCeilx(GGLfixed v) {
+    return gglFixedToIntCeil(v)<<FIXED_BITS;
+}
+GGLfixed gglCenterx(GGLfixed v) {
+    return gglFloorx(v + FIXED_HALF) | FIXED_HALF;
+}
+GGLfixed gglRoundx(GGLfixed v) {
+    return gglFixedToIntRound(v)<<FIXED_BITS;
+}
+
+// conversion from (unsigned) int, short, byte to fixed...
+#define GGL_B_TO_X(_x)      GGLfixed( ((int32_t(_x)+1)>>1)<<10 )
+#define GGL_S_TO_X(_x)      GGLfixed( ((int32_t(_x)+1)>>1)<<2 )
+#define GGL_I_TO_X(_x)      GGLfixed( ((int32_t(_x)>>1)+1)>>14 )
+#define GGL_UB_TO_X(_x)     GGLfixed(   uint32_t(_x) +      \
+                                        (uint32_t(_x)<<8) + \
+                                        (uint32_t(_x)>>7) )
+#define GGL_US_TO_X(_x)     GGLfixed( (_x) + ((_x)>>15) )
+#define GGL_UI_TO_X(_x)     GGLfixed( (((_x)>>1)+1)>>15 )
+
+// ----------------------------------------------------------------------------
+
+GGLfixed gglPowx(GGLfixed x, GGLfixed y) CONST;
+GGLfixed gglSqrtx(GGLfixed a) CONST;
+GGLfixed gglSqrtRecipx(GGLfixed x) CONST;
+GGLfixed gglFastDivx(GGLfixed n, GGLfixed d) CONST;
+int32_t gglMulDivi(int32_t a, int32_t b, int32_t c);
+
+int32_t gglRecipQNormalized(int32_t x, int* exponent);
+int32_t gglRecipQ(GGLfixed x, int q) CONST;
+
+inline GGLfixed gglRecip(GGLfixed x) CONST;
+inline GGLfixed gglRecip(GGLfixed x) {
+    return gglRecipQ(x, 16);
+}
+
+inline GGLfixed gglRecip28(GGLfixed x) CONST;
+int32_t gglRecip28(GGLfixed x) {
+    return gglRecipQ(x, 28);
+}
+
+// ----------------------------------------------------------------------------
+
+#if defined(__arm__) && !defined(__thumb__)
+
+// inline ARM implementations
+inline GGLfixed gglMulx(GGLfixed x, GGLfixed y, int shift) CONST;
+inline GGLfixed gglMulx(GGLfixed x, GGLfixed y, int shift) {
+    GGLfixed result, t;
+    if (__builtin_constant_p(shift)) {
+    asm("smull  %[lo], %[hi], %[x], %[y]            \n"
+        "movs   %[lo], %[lo], lsr %[rshift]         \n"
+        "adc    %[lo], %[lo], %[hi], lsl %[lshift]  \n"
+        : [lo]"=r"(result), [hi]"=r"(t), [x]"=r"(x)
+        : "%[x]"(x), [y]"r"(y), [lshift] "I"(32-shift), [rshift] "I"(shift)
+        : "cc"
+        );
+    } else {
+    asm("smull  %[lo], %[hi], %[x], %[y]            \n"
+        "movs   %[lo], %[lo], lsr %[rshift]         \n"
+        "adc    %[lo], %[lo], %[hi], lsl %[lshift]  \n"
+        : [lo]"=&r"(result), [hi]"=&r"(t), [x]"=&r"(x)
+        : "%[x]"(x), [y]"r"(y), [lshift] "r"(32-shift), [rshift] "r"(shift)
+        : "cc"
+        );
+    }
+    return result;
+}
+
+inline GGLfixed gglMulAddx(GGLfixed x, GGLfixed y, GGLfixed a, int shift) CONST;
+inline GGLfixed gglMulAddx(GGLfixed x, GGLfixed y, GGLfixed a, int shift) {
+    GGLfixed result, t;
+    if (__builtin_constant_p(shift)) {
+    asm("smull  %[lo], %[hi], %[x], %[y]            \n"
+        "add    %[lo], %[a],  %[lo], lsr %[rshift]  \n"
+        "add    %[lo], %[lo], %[hi], lsl %[lshift]  \n"
+        : [lo]"=&r"(result), [hi]"=&r"(t), [x]"=&r"(x)
+        : "%[x]"(x), [y]"r"(y), [a]"r"(a), [lshift] "I"(32-shift), [rshift] "I"(shift)
+        );
+    } else {
+    asm("smull  %[lo], %[hi], %[x], %[y]            \n"
+        "add    %[lo], %[a],  %[lo], lsr %[rshift]  \n"
+        "add    %[lo], %[lo], %[hi], lsl %[lshift]  \n"
+        : [lo]"=&r"(result), [hi]"=&r"(t), [x]"=&r"(x)
+        : "%[x]"(x), [y]"r"(y), [a]"r"(a), [lshift] "r"(32-shift), [rshift] "r"(shift)
+        );
+    }
+    return result;
+}
+
+inline GGLfixed gglMulSubx(GGLfixed x, GGLfixed y, GGLfixed a, int shift) CONST;
+inline GGLfixed gglMulSubx(GGLfixed x, GGLfixed y, GGLfixed a, int shift) {
+    GGLfixed result, t;
+    if (__builtin_constant_p(shift)) {
+    asm("smull  %[lo], %[hi], %[x], %[y]            \n"
+        "rsb    %[lo], %[a],  %[lo], lsr %[rshift]  \n"
+        "add    %[lo], %[lo], %[hi], lsl %[lshift]  \n"
+        : [lo]"=&r"(result), [hi]"=&r"(t), [x]"=&r"(x)
+        : "%[x]"(x), [y]"r"(y), [a]"r"(a), [lshift] "I"(32-shift), [rshift] "I"(shift)
+        );
+    } else {
+    asm("smull  %[lo], %[hi], %[x], %[y]            \n"
+        "rsb    %[lo], %[a],  %[lo], lsr %[rshift]  \n"
+        "add    %[lo], %[lo], %[hi], lsl %[lshift]  \n"
+        : [lo]"=&r"(result), [hi]"=&r"(t), [x]"=&r"(x)
+        : "%[x]"(x), [y]"r"(y), [a]"r"(a), [lshift] "r"(32-shift), [rshift] "r"(shift)
+        );
+    }
+    return result;
+}
+
+inline int64_t gglMulii(int32_t x, int32_t y) CONST;
+inline int64_t gglMulii(int32_t x, int32_t y)
+{
+    // 64-bits result: r0=low, r1=high
+    union {
+        struct {
+            int32_t lo;
+            int32_t hi;
+        } s;
+        int64_t res;
+    };
+    asm("smull %0, %1, %2, %3   \n"
+        : "=r"(s.lo), "=&r"(s.hi)
+        : "%r"(x), "r"(y)
+        :
+        );
+    return res;
+}
+#elif defined(__mips__)
+
+/*inline MIPS implementations*/
+inline GGLfixed gglMulx(GGLfixed a, GGLfixed b, int shift) CONST;
+inline GGLfixed gglMulx(GGLfixed a, GGLfixed b, int shift) {
+    GGLfixed result,tmp,tmp1,tmp2;
+
+    if (__builtin_constant_p(shift)) {
+        if (shift == 0) {
+            asm ("mult %[a], %[b] \t\n"
+              "mflo  %[res]   \t\n"
+            : [res]"=&r"(result),[tmp]"=&r"(tmp)
+            : [a]"r"(a),[b]"r"(b)
+            : "%hi","%lo"
+            );
+        } else if (shift == 32)
+        {
+            asm ("mult %[a], %[b] \t\n"
+            "li  %[tmp],1\t\n"
+            "sll  %[tmp],%[tmp],0x1f\t\n"
+            "mflo %[res]   \t\n"
+            "addu %[tmp1],%[tmp],%[res] \t\n"
+            "sltu %[tmp1],%[tmp1],%[tmp]\t\n"   /*obit*/
+            "sra %[tmp],%[tmp],0x1f \t\n"
+            "mfhi  %[res]   \t\n"
+            "addu %[res],%[res],%[tmp]\t\n"
+            "addu %[res],%[res],%[tmp1]\t\n"
+            : [res]"=&r"(result),[tmp]"=&r"(tmp),[tmp1]"=&r"(tmp1)
+            : [a]"r"(a),[b]"r"(b),[shift]"I"(shift)
+            : "%hi","%lo"
+            );
+        } else if ((shift >0) && (shift < 32))
+        {
+            asm ("mult %[a], %[b] \t\n"
+            "li  %[tmp],1 \t\n"
+            "sll  %[tmp],%[tmp],%[shiftm1] \t\n"
+            "mflo  %[res]   \t\n"
+            "addu %[tmp1],%[tmp],%[res] \t\n"
+            "sltu %[tmp1],%[tmp1],%[tmp] \t\n"  /*obit?*/
+            "addu  %[res],%[res],%[tmp] \t\n"
+            "mfhi  %[tmp]   \t\n"
+            "addu  %[tmp],%[tmp],%[tmp1] \t\n"
+            "sll   %[tmp],%[tmp],%[lshift] \t\n"
+            "srl   %[res],%[res],%[rshift]    \t\n"
+            "or    %[res],%[res],%[tmp] \t\n"
+            : [res]"=&r"(result),[tmp]"=&r"(tmp),[tmp1]"=&r"(tmp1),[tmp2]"=&r"(tmp2)
+            : [a]"r"(a),[b]"r"(b),[lshift]"I"(32-shift),[rshift]"I"(shift),[shiftm1]"I"(shift-1)
+            : "%hi","%lo"
+            );
+        } else {
+            asm ("mult %[a], %[b] \t\n"
+            "li  %[tmp],1 \t\n"
+            "sll  %[tmp],%[tmp],%[shiftm1] \t\n"
+            "mflo  %[res]   \t\n"
+            "addu %[tmp1],%[tmp],%[res] \t\n"
+            "sltu %[tmp1],%[tmp1],%[tmp] \t\n"  /*obit?*/
+            "sra  %[tmp2],%[tmp],0x1f \t\n"
+            "addu  %[res],%[res],%[tmp] \t\n"
+            "mfhi  %[tmp]   \t\n"
+            "addu  %[tmp],%[tmp],%[tmp2] \t\n"
+            "addu  %[tmp],%[tmp],%[tmp1] \t\n"            /*tmp=hi*/
+            "srl   %[tmp2],%[res],%[rshift]    \t\n"
+            "srav  %[res], %[tmp],%[rshift]\t\n"
+            "sll   %[tmp],%[tmp],1 \t\n"
+            "sll   %[tmp],%[tmp],%[norbits] \t\n"
+            "or    %[tmp],%[tmp],%[tmp2] \t\n"
+            "movz  %[res],%[tmp],%[bit5] \t\n"
+            : [res]"=&r"(result),[tmp]"=&r"(tmp),[tmp1]"=&r"(tmp1),[tmp2]"=&r"(tmp2)
+            : [a]"r"(a),[b]"r"(b),[norbits]"I"(~(shift)),[rshift]"I"(shift),[shiftm1] "I"(shift-1),[bit5]"I"(shift & 0x20)
+            : "%hi","%lo"
+            );
+        }
+    } else {
+        asm ("mult %[a], %[b] \t\n"
+        "li  %[tmp],1 \t\n"
+        "sll  %[tmp],%[tmp],%[shiftm1] \t\n"
+        "mflo  %[res]   \t\n"
+        "addu %[tmp1],%[tmp],%[res] \t\n"
+        "sltu %[tmp1],%[tmp1],%[tmp] \t\n"  /*obit?*/
+        "sra  %[tmp2],%[tmp],0x1f \t\n"
+        "addu  %[res],%[res],%[tmp] \t\n"
+        "mfhi  %[tmp]   \t\n"
+        "addu  %[tmp],%[tmp],%[tmp2] \t\n"
+        "addu  %[tmp],%[tmp],%[tmp1] \t\n"            /*tmp=hi*/
+        "srl   %[tmp2],%[res],%[rshift]    \t\n"
+        "srav  %[res], %[tmp],%[rshift]\t\n"
+        "sll   %[tmp],%[tmp],1 \t\n"
+        "sll   %[tmp],%[tmp],%[norbits] \t\n"
+        "or    %[tmp],%[tmp],%[tmp2] \t\n"
+        "movz  %[res],%[tmp],%[bit5] \t\n"
+         : [res]"=&r"(result),[tmp]"=&r"(tmp),[tmp1]"=&r"(tmp1),[tmp2]"=&r"(tmp2)
+         : [a]"r"(a),[b]"r"(b),[norbits]"r"(~(shift)),[rshift] "r"(shift),[shiftm1]"r"(shift-1),[bit5] "r"(shift & 0x20)
+         : "%hi","%lo"
+         );
+        }
+
+        return result;
+}
+
+inline GGLfixed gglMulAddx(GGLfixed a, GGLfixed b, GGLfixed c, int shift) CONST;
+inline GGLfixed gglMulAddx(GGLfixed a, GGLfixed b, GGLfixed c, int shift) {
+    GGLfixed result,t,tmp1,tmp2;
+
+    if (__builtin_constant_p(shift)) {
+        if (shift == 0) {
+                 asm ("mult %[a], %[b] \t\n"
+                 "mflo  %[lo]   \t\n"
+                 "addu  %[lo],%[lo],%[c]    \t\n"
+                 : [lo]"=&r"(result)
+                 : [a]"r"(a),[b]"r"(b),[c]"r"(c)
+                 : "%hi","%lo"
+                 );
+                } else if (shift == 32) {
+                    asm ("mult %[a], %[b] \t\n"
+                    "mfhi  %[lo]   \t\n"
+                    "addu  %[lo],%[lo],%[c]    \t\n"
+                    : [lo]"=&r"(result)
+                    : [a]"r"(a),[b]"r"(b),[c]"r"(c)
+                    : "%hi","%lo"
+                    );
+                } else if ((shift>0) && (shift<32)) {
+                    asm ("mult %[a], %[b] \t\n"
+                    "mflo  %[res]   \t\n"
+                    "mfhi  %[t]   \t\n"
+                    "srl   %[res],%[res],%[rshift]    \t\n"
+                    "sll   %[t],%[t],%[lshift]     \t\n"
+                    "or  %[res],%[res],%[t]    \t\n"
+                    "addu  %[res],%[res],%[c]    \t\n"
+                    : [res]"=&r"(result),[t]"=&r"(t)
+                    : [a]"r"(a),[b]"r"(b),[c]"r"(c),[lshift]"I"(32-shift),[rshift]"I"(shift)
+                    : "%hi","%lo"
+                    );
+                } else {
+                    asm ("mult %[a], %[b] \t\n"
+                    "nor %[tmp1],$zero,%[shift]\t\n"
+                    "mflo  %[res]   \t\n"
+                    "mfhi  %[t]   \t\n"
+                    "srl   %[res],%[res],%[shift]    \t\n"
+                    "sll   %[tmp2],%[t],1     \t\n"
+                    "sllv  %[tmp2],%[tmp2],%[tmp1]     \t\n"
+                    "or  %[tmp1],%[tmp2],%[res]    \t\n"
+                    "srav  %[res],%[t],%[shift]     \t\n"
+                    "andi %[tmp2],%[shift],0x20\t\n"
+                    "movz %[res],%[tmp1],%[tmp2]\t\n"
+                    "addu  %[res],%[res],%[c]    \t\n"
+                    : [res]"=&r"(result),[t]"=&r"(t),[tmp1]"=&r"(tmp1),[tmp2]"=&r"(tmp2)
+                    : [a]"r"(a),[b]"r"(b),[c]"r"(c),[shift]"I"(shift)
+                    : "%hi","%lo"
+                    );
+                }
+            } else {
+                asm ("mult %[a], %[b] \t\n"
+                "nor %[tmp1],$zero,%[shift]\t\n"
+                "mflo  %[res]   \t\n"
+                "mfhi  %[t]   \t\n"
+                "srl   %[res],%[res],%[shift]    \t\n"
+                "sll   %[tmp2],%[t],1     \t\n"
+                "sllv  %[tmp2],%[tmp2],%[tmp1]     \t\n"
+                "or  %[tmp1],%[tmp2],%[res]    \t\n"
+                "srav  %[res],%[t],%[shift]     \t\n"
+                "andi %[tmp2],%[shift],0x20\t\n"
+                "movz %[res],%[tmp1],%[tmp2]\t\n"
+                "addu  %[res],%[res],%[c]    \t\n"
+                : [res]"=&r"(result),[t]"=&r"(t),[tmp1]"=&r"(tmp1),[tmp2]"=&r"(tmp2)
+                : [a]"r"(a),[b]"r"(b),[c]"r"(c),[shift]"r"(shift)
+                : "%hi","%lo"
+                );
+            }
+            return result;
+}
+
+inline GGLfixed gglMulSubx(GGLfixed a, GGLfixed b, GGLfixed c, int shift) CONST;
+inline GGLfixed gglMulSubx(GGLfixed a, GGLfixed b, GGLfixed c, int shift) {
+    GGLfixed result,t,tmp1,tmp2;
+
+    if (__builtin_constant_p(shift)) {
+        if (shift == 0) {
+                 asm ("mult %[a], %[b] \t\n"
+                 "mflo  %[lo]   \t\n"
+                 "subu  %[lo],%[lo],%[c]    \t\n"
+                 : [lo]"=&r"(result)
+                 : [a]"r"(a),[b]"r"(b),[c]"r"(c)
+                 : "%hi","%lo"
+                 );
+                } else if (shift == 32) {
+                    asm ("mult %[a], %[b] \t\n"
+                    "mfhi  %[lo]   \t\n"
+                    "subu  %[lo],%[lo],%[c]    \t\n"
+                    : [lo]"=&r"(result)
+                    : [a]"r"(a),[b]"r"(b),[c]"r"(c)
+                    : "%hi","%lo"
+                    );
+                } else if ((shift>0) && (shift<32)) {
+                    asm ("mult %[a], %[b] \t\n"
+                    "mflo  %[res]   \t\n"
+                    "mfhi  %[t]   \t\n"
+                    "srl   %[res],%[res],%[rshift]    \t\n"
+                    "sll   %[t],%[t],%[lshift]     \t\n"
+                    "or  %[res],%[res],%[t]    \t\n"
+                    "subu  %[res],%[res],%[c]    \t\n"
+                    : [res]"=&r"(result),[t]"=&r"(t)
+                    : [a]"r"(a),[b]"r"(b),[c]"r"(c),[lshift]"I"(32-shift),[rshift]"I"(shift)
+                    : "%hi","%lo"
+                    );
+                } else {
+                    asm ("mult %[a], %[b] \t\n"
+                    "nor %[tmp1],$zero,%[shift]\t\n"
+                     "mflo  %[res]   \t\n"
+                     "mfhi  %[t]   \t\n"
+                     "srl   %[res],%[res],%[shift]    \t\n"
+                     "sll   %[tmp2],%[t],1     \t\n"
+                     "sllv  %[tmp2],%[tmp2],%[tmp1]     \t\n"
+                     "or  %[tmp1],%[tmp2],%[res]    \t\n"
+                     "srav  %[res],%[t],%[shift]     \t\n"
+                     "andi %[tmp2],%[shift],0x20\t\n"
+                     "movz %[res],%[tmp1],%[tmp2]\t\n"
+                     "subu  %[res],%[res],%[c]    \t\n"
+                     : [res]"=&r"(result),[t]"=&r"(t),[tmp1]"=&r"(tmp1),[tmp2]"=&r"(tmp2)
+                     : [a]"r"(a),[b]"r"(b),[c]"r"(c),[shift]"I"(shift)
+                     : "%hi","%lo"
+                     );
+                    }
+                } else {
+                asm ("mult %[a], %[b] \t\n"
+                "nor %[tmp1],$zero,%[shift]\t\n"
+                "mflo  %[res]   \t\n"
+                "mfhi  %[t]   \t\n"
+                "srl   %[res],%[res],%[shift]    \t\n"
+                "sll   %[tmp2],%[t],1     \t\n"
+                "sllv  %[tmp2],%[tmp2],%[tmp1]     \t\n"
+                "or  %[tmp1],%[tmp2],%[res]    \t\n"
+                "srav  %[res],%[t],%[shift]     \t\n"
+                "andi %[tmp2],%[shift],0x20\t\n"
+                "movz %[res],%[tmp1],%[tmp2]\t\n"
+                "subu  %[res],%[res],%[c]    \t\n"
+                : [res]"=&r"(result),[t]"=&r"(t),[tmp1]"=&r"(tmp1),[tmp2]"=&r"(tmp2)
+                : [a]"r"(a),[b]"r"(b),[c]"r"(c),[shift]"r"(shift)
+                : "%hi","%lo"
+                );
+            }
+    return result;
+}
+
+inline int64_t gglMulii(int32_t x, int32_t y) CONST;
+inline int64_t gglMulii(int32_t x, int32_t y) {
+    union {
+        struct {
+#if defined(__MIPSEL__)
+            int32_t lo;
+            int32_t hi;
+#elif defined(__MIPSEB__)
+            int32_t hi;
+            int32_t lo;
+#endif
+        } s;
+        int64_t res;
+    }u;
+    asm("mult %2, %3 \t\n"
+        "mfhi %1   \t\n"
+        "mflo %0   \t\n"
+        : "=r"(u.s.lo), "=&r"(u.s.hi)
+        : "%r"(x), "r"(y)
+	: "%hi","%lo"
+        );
+    return u.res;
+}
+
+#elif defined(__aarch64__)
+
+// inline AArch64 implementations
+
+inline GGLfixed gglMulx(GGLfixed x, GGLfixed y, int shift) CONST;
+inline GGLfixed gglMulx(GGLfixed x, GGLfixed y, int shift)
+{
+    GGLfixed result;
+    GGLfixed round;
+
+    asm("mov    %x[round], #1                        \n"
+        "lsl    %x[round], %x[round], %x[shift]      \n"
+        "lsr    %x[round], %x[round], #1             \n"
+        "smaddl %x[result], %w[x], %w[y],%x[round]   \n"
+        "lsr    %x[result], %x[result], %x[shift]    \n"
+        : [round]"=&r"(round), [result]"=&r"(result) \
+        : [x]"r"(x), [y]"r"(y), [shift] "r"(shift)   \
+        :
+       );
+    return result;
+}
+inline GGLfixed gglMulAddx(GGLfixed x, GGLfixed y, GGLfixed a, int shift) CONST;
+inline GGLfixed gglMulAddx(GGLfixed x, GGLfixed y, GGLfixed a, int shift)
+{
+    GGLfixed result;
+    asm("smull  %x[result], %w[x], %w[y]                     \n"
+        "lsr    %x[result], %x[result], %x[shift]            \n"
+        "add    %w[result], %w[result], %w[a]                \n"
+        : [result]"=&r"(result)                               \
+        : [x]"r"(x), [y]"r"(y), [a]"r"(a), [shift] "r"(shift) \
+        :
+        );
+    return result;
+}
+
+inline GGLfixed gglMulSubx(GGLfixed x, GGLfixed y, GGLfixed a, int shift) CONST;
+inline GGLfixed gglMulSubx(GGLfixed x, GGLfixed y, GGLfixed a, int shift)
+{
+
+    GGLfixed result;
+    int rshift;
+
+    asm("smull  %x[result], %w[x], %w[y]                     \n"
+        "lsr    %x[result], %x[result], %x[shift]            \n"
+        "sub    %w[result], %w[result], %w[a]                \n"
+        : [result]"=&r"(result)                               \
+        : [x]"r"(x), [y]"r"(y), [a]"r"(a), [shift] "r"(shift) \
+        :
+        );
+    return result;
+}
+inline int64_t gglMulii(int32_t x, int32_t y) CONST;
+inline int64_t gglMulii(int32_t x, int32_t y)
+{
+    int64_t res;
+    asm("smull  %x0, %w1, %w2 \n"
+        : "=r"(res)
+        : "%r"(x), "r"(y)
+        :
+        );
+    return res;
+}
+
+#else // ----------------------------------------------------------------------
+
+inline GGLfixed gglMulx(GGLfixed a, GGLfixed b, int shift) CONST;
+inline GGLfixed gglMulx(GGLfixed a, GGLfixed b, int shift) {
+    return GGLfixed((int64_t(a)*b + (1<<(shift-1)))>>shift);
+}
+inline GGLfixed gglMulAddx(GGLfixed a, GGLfixed b, GGLfixed c, int shift) CONST;
+inline GGLfixed gglMulAddx(GGLfixed a, GGLfixed b, GGLfixed c, int shift) {
+    return GGLfixed((int64_t(a)*b)>>shift) + c;
+}
+inline GGLfixed gglMulSubx(GGLfixed a, GGLfixed b, GGLfixed c, int shift) CONST;
+inline GGLfixed gglMulSubx(GGLfixed a, GGLfixed b, GGLfixed c, int shift) {
+    return GGLfixed((int64_t(a)*b)>>shift) - c;
+}
+inline int64_t gglMulii(int32_t a, int32_t b) CONST;
+inline int64_t gglMulii(int32_t a, int32_t b) {
+    return int64_t(a)*b;
+}
+
+#endif
+
+// ------------------------------------------------------------------------
+
+inline GGLfixed gglMulx(GGLfixed a, GGLfixed b) CONST;
+inline GGLfixed gglMulx(GGLfixed a, GGLfixed b) {
+    return gglMulx(a, b, 16);
+}
+inline GGLfixed gglMulAddx(GGLfixed a, GGLfixed b, GGLfixed c) CONST;
+inline GGLfixed gglMulAddx(GGLfixed a, GGLfixed b, GGLfixed c) {
+    return gglMulAddx(a, b, c, 16);
+}
+inline GGLfixed gglMulSubx(GGLfixed a, GGLfixed b, GGLfixed c) CONST;
+inline GGLfixed gglMulSubx(GGLfixed a, GGLfixed b, GGLfixed c) {
+    return gglMulSubx(a, b, c, 16);
+}
+
+// ------------------------------------------------------------------------
+
+inline int32_t gglClz(int32_t x) CONST;
+inline int32_t gglClz(int32_t x)
+{
+#if (defined(__arm__) && !defined(__thumb__)) || defined(__mips__) || defined(__aarch64__)
+    return __builtin_clz(x);
+#else
+    if (!x) return 32;
+    int32_t exp = 31;
+    if (x & 0xFFFF0000) { exp -=16; x >>= 16; }
+    if (x & 0x0000ff00) { exp -= 8; x >>= 8; }
+    if (x & 0x000000f0) { exp -= 4; x >>= 4; }
+    if (x & 0x0000000c) { exp -= 2; x >>= 2; }
+    if (x & 0x00000002) { exp -= 1; }
+    return exp;
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+int32_t gglDivQ(GGLfixed n, GGLfixed d, int32_t i) CONST;
+
+inline int32_t gglDivQ16(GGLfixed n, GGLfixed d) CONST;
+inline int32_t gglDivQ16(GGLfixed n, GGLfixed d) {
+    return gglDivQ(n, d, 16);
+}
+
+inline int32_t gglDivx(GGLfixed n, GGLfixed d) CONST;
+inline int32_t gglDivx(GGLfixed n, GGLfixed d) {
+    return gglDivQ(n, d, 16);
+}
+
+// ------------------------------------------------------------------------
+
+inline GGLfixed gglRecipFast(GGLfixed x) CONST;
+inline GGLfixed gglRecipFast(GGLfixed x)
+{
+    // This is a really bad approximation of 1/x, but it's also
+    // very fast. x must be strictly positive.
+    // if x between [0.5, 1[ , then 1/x = 3-2*x
+    // (we use 2.30 fixed-point)
+    const int32_t lz = gglClz(x);
+    return (0xC0000000 - (x << (lz - 1))) >> (30-lz);
+}
+
+// ------------------------------------------------------------------------
+
+inline GGLfixed gglClampx(GGLfixed c) CONST;
+inline GGLfixed gglClampx(GGLfixed c)
+{
+#if defined(__thumb__)
+    // clamp without branches
+    c &= ~(c>>31);  c = FIXED_ONE - c;
+    c &= ~(c>>31);  c = FIXED_ONE - c;
+#else
+#if defined(__arm__)
+    // I don't know why gcc thinks its smarter than me! The code below
+    // clamps to zero in one instruction, but gcc won't generate it and
+    // replace it by a cmp + movlt (it's quite amazing actually).
+    asm("bic %0, %1, %1, asr #31\n" : "=r"(c) : "r"(c));
+#elif defined(__aarch64__)
+    asm("bic %w0, %w1, %w1, asr #31\n" : "=r"(c) : "r"(c));
+#else
+    c &= ~(c>>31);
+#endif
+    if (c>FIXED_ONE)
+        c = FIXED_ONE;
+#endif
+    return c;
+}
+
+// ------------------------------------------------------------------------
+
+#endif // ANDROID_GGL_FIXED_H
diff --git a/package/utils/adbd/src/include/system/audio.h b/package/utils/adbd/src/include/system/audio.h
new file mode 100644
index 0000000..b1827b0
--- /dev/null
+++ b/package/utils/adbd/src/include/system/audio.h
@@ -0,0 +1,1059 @@
+/*
+ * Copyright (C) 2011 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 ANDROID_AUDIO_CORE_H
+#define ANDROID_AUDIO_CORE_H
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <cutils/bitops.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/* The enums were moved here mostly from
+ * frameworks/base/include/media/AudioSystem.h
+ */
+
+/* device address used to refer to the standard remote submix */
+#define AUDIO_REMOTE_SUBMIX_DEVICE_ADDRESS "0"
+
+/* AudioFlinger and AudioPolicy services use I/O handles to identify audio sources and sinks */
+typedef int audio_io_handle_t;
+#define AUDIO_IO_HANDLE_NONE    0
+
+/* Audio stream types */
+typedef enum {
+    /* These values must kept in sync with
+     * frameworks/base/media/java/android/media/AudioSystem.java
+     */
+    AUDIO_STREAM_DEFAULT          = -1,
+    AUDIO_STREAM_MIN              = 0,
+    AUDIO_STREAM_VOICE_CALL       = 0,
+    AUDIO_STREAM_SYSTEM           = 1,
+    AUDIO_STREAM_RING             = 2,
+    AUDIO_STREAM_MUSIC            = 3,
+    AUDIO_STREAM_ALARM            = 4,
+    AUDIO_STREAM_NOTIFICATION     = 5,
+    AUDIO_STREAM_BLUETOOTH_SCO    = 6,
+    AUDIO_STREAM_ENFORCED_AUDIBLE = 7, /* Sounds that cannot be muted by user and must be routed to speaker */
+    AUDIO_STREAM_DTMF             = 8,
+    AUDIO_STREAM_TTS              = 9,
+
+    AUDIO_STREAM_CNT,
+    AUDIO_STREAM_MAX              = AUDIO_STREAM_CNT - 1,
+} audio_stream_type_t;
+
+/* Do not change these values without updating their counterparts
+ * in frameworks/base/media/java/android/media/AudioAttributes.java
+ */
+typedef enum {
+    AUDIO_CONTENT_TYPE_UNKNOWN      = 0,
+    AUDIO_CONTENT_TYPE_SPEECH       = 1,
+    AUDIO_CONTENT_TYPE_MUSIC        = 2,
+    AUDIO_CONTENT_TYPE_MOVIE        = 3,
+    AUDIO_CONTENT_TYPE_SONIFICATION = 4,
+
+    AUDIO_CONTENT_TYPE_CNT,
+    AUDIO_CONTENT_TYPE_MAX          = AUDIO_CONTENT_TYPE_CNT - 1,
+} audio_content_type_t;
+
+/* Do not change these values without updating their counterparts
+ * in frameworks/base/media/java/android/media/AudioAttributes.java
+ */
+typedef enum {
+    AUDIO_USAGE_UNKNOWN                            = 0,
+    AUDIO_USAGE_MEDIA                              = 1,
+    AUDIO_USAGE_VOICE_COMMUNICATION                = 2,
+    AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING     = 3,
+    AUDIO_USAGE_ALARM                              = 4,
+    AUDIO_USAGE_NOTIFICATION                       = 5,
+    AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE    = 6,
+    AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST = 7,
+    AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT = 8,
+    AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED = 9,
+    AUDIO_USAGE_NOTIFICATION_EVENT                 = 10,
+    AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY           = 11,
+    AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE     = 12,
+    AUDIO_USAGE_ASSISTANCE_SONIFICATION            = 13,
+    AUDIO_USAGE_GAME                               = 14,
+
+    AUDIO_USAGE_CNT,
+    AUDIO_USAGE_MAX                                = AUDIO_USAGE_CNT - 1,
+} audio_usage_t;
+
+typedef uint32_t audio_flags_mask_t;
+
+/* Do not change these values without updating their counterparts
+ * in frameworks/base/media/java/android/media/AudioAttributes.java
+ */
+enum {
+    AUDIO_FLAG_AUDIBILITY_ENFORCED = 0x1,
+    AUDIO_FLAG_SECURE              = 0x2,
+    AUDIO_FLAG_SCO                 = 0x4,
+};
+
+/* Do not change these values without updating their counterparts
+ * in frameworks/base/media/java/android/media/MediaRecorder.java,
+ * frameworks/av/services/audiopolicy/AudioPolicyService.cpp,
+ * and system/media/audio_effects/include/audio_effects/audio_effects_conf.h!
+ */
+typedef enum {
+    AUDIO_SOURCE_DEFAULT             = 0,
+    AUDIO_SOURCE_MIC                 = 1,
+    AUDIO_SOURCE_VOICE_UPLINK        = 2,
+    AUDIO_SOURCE_VOICE_DOWNLINK      = 3,
+    AUDIO_SOURCE_VOICE_CALL          = 4,
+    AUDIO_SOURCE_CAMCORDER           = 5,
+    AUDIO_SOURCE_VOICE_RECOGNITION   = 6,
+    AUDIO_SOURCE_VOICE_COMMUNICATION = 7,
+    AUDIO_SOURCE_REMOTE_SUBMIX       = 8, /* Source for the mix to be presented remotely.      */
+                                          /* An example of remote presentation is Wifi Display */
+                                          /*  where a dongle attached to a TV can be used to   */
+                                          /*  play the mix captured by this audio source.      */
+    AUDIO_SOURCE_CNT,
+    AUDIO_SOURCE_MAX                 = AUDIO_SOURCE_CNT - 1,
+    AUDIO_SOURCE_HOTWORD             = 1999, /* A low-priority, preemptible audio source for
+                                                for background software hotword detection.
+                                                Same tuning as AUDIO_SOURCE_VOICE_RECOGNITION.
+                                                Used only internally to the framework. Not exposed
+                                                at the audio HAL. */
+} audio_source_t;
+
+/* Audio attributes */
+#define AUDIO_ATTRIBUTES_TAGS_MAX_SIZE 256
+typedef struct {
+    audio_content_type_t content_type;
+    audio_usage_t        usage;
+    audio_source_t       source;
+    audio_flags_mask_t   flags;
+    char                 tags[AUDIO_ATTRIBUTES_TAGS_MAX_SIZE]; /* UTF8 */
+} audio_attributes_t;
+
+/* special audio session values
+ * (XXX: should this be living in the audio effects land?)
+ */
+typedef enum {
+    /* session for effects attached to a particular output stream
+     * (value must be less than 0)
+     */
+    AUDIO_SESSION_OUTPUT_STAGE = -1,
+
+    /* session for effects applied to output mix. These effects can
+     * be moved by audio policy manager to another output stream
+     * (value must be 0)
+     */
+    AUDIO_SESSION_OUTPUT_MIX = 0,
+
+    /* application does not specify an explicit session ID to be used,
+     * and requests a new session ID to be allocated
+     * TODO use unique values for AUDIO_SESSION_OUTPUT_MIX and AUDIO_SESSION_ALLOCATE,
+     * after all uses have been updated from 0 to the appropriate symbol, and have been tested.
+     */
+    AUDIO_SESSION_ALLOCATE = 0,
+} audio_session_t;
+
+/* Audio sub formats (see enum audio_format). */
+
+/* PCM sub formats */
+typedef enum {
+    /* All of these are in native byte order */
+    AUDIO_FORMAT_PCM_SUB_16_BIT          = 0x1, /* DO NOT CHANGE - PCM signed 16 bits */
+    AUDIO_FORMAT_PCM_SUB_8_BIT           = 0x2, /* DO NOT CHANGE - PCM unsigned 8 bits */
+    AUDIO_FORMAT_PCM_SUB_32_BIT          = 0x3, /* PCM signed .31 fixed point */
+    AUDIO_FORMAT_PCM_SUB_8_24_BIT        = 0x4, /* PCM signed 7.24 fixed point */
+    AUDIO_FORMAT_PCM_SUB_FLOAT           = 0x5, /* PCM single-precision floating point */
+    AUDIO_FORMAT_PCM_SUB_24_BIT_PACKED   = 0x6, /* PCM signed .23 fixed point packed in 3 bytes */
+} audio_format_pcm_sub_fmt_t;
+
+/* The audio_format_*_sub_fmt_t declarations are not currently used */
+
+/* MP3 sub format field definition : can use 11 LSBs in the same way as MP3
+ * frame header to specify bit rate, stereo mode, version...
+ */
+typedef enum {
+    AUDIO_FORMAT_MP3_SUB_NONE            = 0x0,
+} audio_format_mp3_sub_fmt_t;
+
+/* AMR NB/WB sub format field definition: specify frame block interleaving,
+ * bandwidth efficient or octet aligned, encoding mode for recording...
+ */
+typedef enum {
+    AUDIO_FORMAT_AMR_SUB_NONE            = 0x0,
+} audio_format_amr_sub_fmt_t;
+
+/* AAC sub format field definition: specify profile or bitrate for recording... */
+typedef enum {
+    AUDIO_FORMAT_AAC_SUB_NONE            = 0x0,
+} audio_format_aac_sub_fmt_t;
+
+/* VORBIS sub format field definition: specify quality for recording... */
+typedef enum {
+    AUDIO_FORMAT_VORBIS_SUB_NONE         = 0x0,
+} audio_format_vorbis_sub_fmt_t;
+
+/* Audio format consists of a main format field (upper 8 bits) and a sub format
+ * field (lower 24 bits).
+ *
+ * The main format indicates the main codec type. The sub format field
+ * indicates options and parameters for each format. The sub format is mainly
+ * used for record to indicate for instance the requested bitrate or profile.
+ * It can also be used for certain formats to give informations not present in
+ * the encoded audio stream (e.g. octet alignement for AMR).
+ */
+typedef enum {
+    AUDIO_FORMAT_INVALID             = 0xFFFFFFFFUL,
+    AUDIO_FORMAT_DEFAULT             = 0,
+    AUDIO_FORMAT_PCM                 = 0x00000000UL, /* DO NOT CHANGE */
+    AUDIO_FORMAT_MP3                 = 0x01000000UL,
+    AUDIO_FORMAT_AMR_NB              = 0x02000000UL,
+    AUDIO_FORMAT_AMR_WB              = 0x03000000UL,
+    AUDIO_FORMAT_AAC                 = 0x04000000UL,
+    AUDIO_FORMAT_HE_AAC_V1           = 0x05000000UL,
+    AUDIO_FORMAT_HE_AAC_V2           = 0x06000000UL,
+    AUDIO_FORMAT_VORBIS              = 0x07000000UL,
+    AUDIO_FORMAT_OPUS                = 0x08000000UL,
+    AUDIO_FORMAT_AC3                 = 0x09000000UL,
+    AUDIO_FORMAT_E_AC3               = 0x0A000000UL,
+    AUDIO_FORMAT_MAIN_MASK           = 0xFF000000UL,
+    AUDIO_FORMAT_SUB_MASK            = 0x00FFFFFFUL,
+
+    /* Aliases */
+    /* note != AudioFormat.ENCODING_PCM_16BIT */
+    AUDIO_FORMAT_PCM_16_BIT          = (AUDIO_FORMAT_PCM |
+                                        AUDIO_FORMAT_PCM_SUB_16_BIT),
+    /* note != AudioFormat.ENCODING_PCM_8BIT */
+    AUDIO_FORMAT_PCM_8_BIT           = (AUDIO_FORMAT_PCM |
+                                        AUDIO_FORMAT_PCM_SUB_8_BIT),
+    AUDIO_FORMAT_PCM_32_BIT          = (AUDIO_FORMAT_PCM |
+                                        AUDIO_FORMAT_PCM_SUB_32_BIT),
+    AUDIO_FORMAT_PCM_8_24_BIT        = (AUDIO_FORMAT_PCM |
+                                        AUDIO_FORMAT_PCM_SUB_8_24_BIT),
+    AUDIO_FORMAT_PCM_FLOAT           = (AUDIO_FORMAT_PCM |
+                                        AUDIO_FORMAT_PCM_SUB_FLOAT),
+    AUDIO_FORMAT_PCM_24_BIT_PACKED   = (AUDIO_FORMAT_PCM |
+                                        AUDIO_FORMAT_PCM_SUB_24_BIT_PACKED),
+} audio_format_t;
+
+enum {
+    AUDIO_CHANNEL_NONE                      = 0x0,
+    /* output channels */
+    AUDIO_CHANNEL_OUT_FRONT_LEFT            = 0x1,
+    AUDIO_CHANNEL_OUT_FRONT_RIGHT           = 0x2,
+    AUDIO_CHANNEL_OUT_FRONT_CENTER          = 0x4,
+    AUDIO_CHANNEL_OUT_LOW_FREQUENCY         = 0x8,
+    AUDIO_CHANNEL_OUT_BACK_LEFT             = 0x10,
+    AUDIO_CHANNEL_OUT_BACK_RIGHT            = 0x20,
+    AUDIO_CHANNEL_OUT_FRONT_LEFT_OF_CENTER  = 0x40,
+    AUDIO_CHANNEL_OUT_FRONT_RIGHT_OF_CENTER = 0x80,
+    AUDIO_CHANNEL_OUT_BACK_CENTER           = 0x100,
+    AUDIO_CHANNEL_OUT_SIDE_LEFT             = 0x200,
+    AUDIO_CHANNEL_OUT_SIDE_RIGHT            = 0x400,
+    AUDIO_CHANNEL_OUT_TOP_CENTER            = 0x800,
+    AUDIO_CHANNEL_OUT_TOP_FRONT_LEFT        = 0x1000,
+    AUDIO_CHANNEL_OUT_TOP_FRONT_CENTER      = 0x2000,
+    AUDIO_CHANNEL_OUT_TOP_FRONT_RIGHT       = 0x4000,
+    AUDIO_CHANNEL_OUT_TOP_BACK_LEFT         = 0x8000,
+    AUDIO_CHANNEL_OUT_TOP_BACK_CENTER       = 0x10000,
+    AUDIO_CHANNEL_OUT_TOP_BACK_RIGHT        = 0x20000,
+
+    AUDIO_CHANNEL_OUT_MONO     = AUDIO_CHANNEL_OUT_FRONT_LEFT,
+    AUDIO_CHANNEL_OUT_STEREO   = (AUDIO_CHANNEL_OUT_FRONT_LEFT |
+                                  AUDIO_CHANNEL_OUT_FRONT_RIGHT),
+    AUDIO_CHANNEL_OUT_QUAD     = (AUDIO_CHANNEL_OUT_FRONT_LEFT |
+                                  AUDIO_CHANNEL_OUT_FRONT_RIGHT |
+                                  AUDIO_CHANNEL_OUT_BACK_LEFT |
+                                  AUDIO_CHANNEL_OUT_BACK_RIGHT),
+    AUDIO_CHANNEL_OUT_QUAD_BACK = AUDIO_CHANNEL_OUT_QUAD,
+    /* like AUDIO_CHANNEL_OUT_QUAD_BACK with *_SIDE_* instead of *_BACK_* */
+    AUDIO_CHANNEL_OUT_QUAD_SIDE = (AUDIO_CHANNEL_OUT_FRONT_LEFT |
+                                  AUDIO_CHANNEL_OUT_FRONT_RIGHT |
+                                  AUDIO_CHANNEL_OUT_SIDE_LEFT |
+                                  AUDIO_CHANNEL_OUT_SIDE_RIGHT),
+    AUDIO_CHANNEL_OUT_5POINT1  = (AUDIO_CHANNEL_OUT_FRONT_LEFT |
+                                  AUDIO_CHANNEL_OUT_FRONT_RIGHT |
+                                  AUDIO_CHANNEL_OUT_FRONT_CENTER |
+                                  AUDIO_CHANNEL_OUT_LOW_FREQUENCY |
+                                  AUDIO_CHANNEL_OUT_BACK_LEFT |
+                                  AUDIO_CHANNEL_OUT_BACK_RIGHT),
+    AUDIO_CHANNEL_OUT_5POINT1_BACK = AUDIO_CHANNEL_OUT_5POINT1,
+    /* like AUDIO_CHANNEL_OUT_5POINT1_BACK with *_SIDE_* instead of *_BACK_* */
+    AUDIO_CHANNEL_OUT_5POINT1_SIDE = (AUDIO_CHANNEL_OUT_FRONT_LEFT |
+                                  AUDIO_CHANNEL_OUT_FRONT_RIGHT |
+                                  AUDIO_CHANNEL_OUT_FRONT_CENTER |
+                                  AUDIO_CHANNEL_OUT_LOW_FREQUENCY |
+                                  AUDIO_CHANNEL_OUT_SIDE_LEFT |
+                                  AUDIO_CHANNEL_OUT_SIDE_RIGHT),
+    // matches the correct AudioFormat.CHANNEL_OUT_7POINT1_SURROUND definition for 7.1
+    AUDIO_CHANNEL_OUT_7POINT1  = (AUDIO_CHANNEL_OUT_FRONT_LEFT |
+                                  AUDIO_CHANNEL_OUT_FRONT_RIGHT |
+                                  AUDIO_CHANNEL_OUT_FRONT_CENTER |
+                                  AUDIO_CHANNEL_OUT_LOW_FREQUENCY |
+                                  AUDIO_CHANNEL_OUT_BACK_LEFT |
+                                  AUDIO_CHANNEL_OUT_BACK_RIGHT |
+                                  AUDIO_CHANNEL_OUT_SIDE_LEFT |
+                                  AUDIO_CHANNEL_OUT_SIDE_RIGHT),
+    AUDIO_CHANNEL_OUT_ALL      = (AUDIO_CHANNEL_OUT_FRONT_LEFT |
+                                  AUDIO_CHANNEL_OUT_FRONT_RIGHT |
+                                  AUDIO_CHANNEL_OUT_FRONT_CENTER |
+                                  AUDIO_CHANNEL_OUT_LOW_FREQUENCY |
+                                  AUDIO_CHANNEL_OUT_BACK_LEFT |
+                                  AUDIO_CHANNEL_OUT_BACK_RIGHT |
+                                  AUDIO_CHANNEL_OUT_FRONT_LEFT_OF_CENTER |
+                                  AUDIO_CHANNEL_OUT_FRONT_RIGHT_OF_CENTER |
+                                  AUDIO_CHANNEL_OUT_BACK_CENTER|
+                                  AUDIO_CHANNEL_OUT_SIDE_LEFT|
+                                  AUDIO_CHANNEL_OUT_SIDE_RIGHT|
+                                  AUDIO_CHANNEL_OUT_TOP_CENTER|
+                                  AUDIO_CHANNEL_OUT_TOP_FRONT_LEFT|
+                                  AUDIO_CHANNEL_OUT_TOP_FRONT_CENTER|
+                                  AUDIO_CHANNEL_OUT_TOP_FRONT_RIGHT|
+                                  AUDIO_CHANNEL_OUT_TOP_BACK_LEFT|
+                                  AUDIO_CHANNEL_OUT_TOP_BACK_CENTER|
+                                  AUDIO_CHANNEL_OUT_TOP_BACK_RIGHT),
+
+    /* input channels */
+    AUDIO_CHANNEL_IN_LEFT            = 0x4,
+    AUDIO_CHANNEL_IN_RIGHT           = 0x8,
+    AUDIO_CHANNEL_IN_FRONT           = 0x10,
+    AUDIO_CHANNEL_IN_BACK            = 0x20,
+    AUDIO_CHANNEL_IN_LEFT_PROCESSED  = 0x40,
+    AUDIO_CHANNEL_IN_RIGHT_PROCESSED = 0x80,
+    AUDIO_CHANNEL_IN_FRONT_PROCESSED = 0x100,
+    AUDIO_CHANNEL_IN_BACK_PROCESSED  = 0x200,
+    AUDIO_CHANNEL_IN_PRESSURE        = 0x400,
+    AUDIO_CHANNEL_IN_X_AXIS          = 0x800,
+    AUDIO_CHANNEL_IN_Y_AXIS          = 0x1000,
+    AUDIO_CHANNEL_IN_Z_AXIS          = 0x2000,
+    AUDIO_CHANNEL_IN_VOICE_UPLINK    = 0x4000,
+    AUDIO_CHANNEL_IN_VOICE_DNLINK    = 0x8000,
+
+    AUDIO_CHANNEL_IN_MONO   = AUDIO_CHANNEL_IN_FRONT,
+    AUDIO_CHANNEL_IN_STEREO = (AUDIO_CHANNEL_IN_LEFT | AUDIO_CHANNEL_IN_RIGHT),
+    AUDIO_CHANNEL_IN_FRONT_BACK = (AUDIO_CHANNEL_IN_FRONT | AUDIO_CHANNEL_IN_BACK),
+    AUDIO_CHANNEL_IN_ALL    = (AUDIO_CHANNEL_IN_LEFT |
+                               AUDIO_CHANNEL_IN_RIGHT |
+                               AUDIO_CHANNEL_IN_FRONT |
+                               AUDIO_CHANNEL_IN_BACK|
+                               AUDIO_CHANNEL_IN_LEFT_PROCESSED |
+                               AUDIO_CHANNEL_IN_RIGHT_PROCESSED |
+                               AUDIO_CHANNEL_IN_FRONT_PROCESSED |
+                               AUDIO_CHANNEL_IN_BACK_PROCESSED|
+                               AUDIO_CHANNEL_IN_PRESSURE |
+                               AUDIO_CHANNEL_IN_X_AXIS |
+                               AUDIO_CHANNEL_IN_Y_AXIS |
+                               AUDIO_CHANNEL_IN_Z_AXIS |
+                               AUDIO_CHANNEL_IN_VOICE_UPLINK |
+                               AUDIO_CHANNEL_IN_VOICE_DNLINK),
+};
+
+/* A channel mask per se only defines the presence or absence of a channel, not the order.
+ * But see AUDIO_INTERLEAVE_* below for the platform convention of order.
+ */
+typedef uint32_t audio_channel_mask_t;
+
+/* Expresses the convention when stereo audio samples are stored interleaved
+ * in an array.  This should improve readability by allowing code to use
+ * symbolic indices instead of hard-coded [0] and [1].
+ *
+ * For multi-channel beyond stereo, the platform convention is that channels
+ * are interleaved in order from least significant channel mask bit
+ * to most significant channel mask bit, with unused bits skipped.
+ * Any exceptions to this convention will be noted at the appropriate API.
+ */
+enum {
+    AUDIO_INTERLEAVE_LEFT   = 0,
+    AUDIO_INTERLEAVE_RIGHT  = 1,
+};
+
+typedef enum {
+    AUDIO_MODE_INVALID          = -2,
+    AUDIO_MODE_CURRENT          = -1,
+    AUDIO_MODE_NORMAL           = 0,
+    AUDIO_MODE_RINGTONE         = 1,
+    AUDIO_MODE_IN_CALL          = 2,
+    AUDIO_MODE_IN_COMMUNICATION = 3,
+
+    AUDIO_MODE_CNT,
+    AUDIO_MODE_MAX              = AUDIO_MODE_CNT - 1,
+} audio_mode_t;
+
+/* This enum is deprecated */
+typedef enum {
+    AUDIO_IN_ACOUSTICS_NONE          = 0,
+    AUDIO_IN_ACOUSTICS_AGC_ENABLE    = 0x0001,
+    AUDIO_IN_ACOUSTICS_AGC_DISABLE   = 0,
+    AUDIO_IN_ACOUSTICS_NS_ENABLE     = 0x0002,
+    AUDIO_IN_ACOUSTICS_NS_DISABLE    = 0,
+    AUDIO_IN_ACOUSTICS_TX_IIR_ENABLE = 0x0004,
+    AUDIO_IN_ACOUSTICS_TX_DISABLE    = 0,
+} audio_in_acoustics_t;
+
+enum {
+    AUDIO_DEVICE_NONE                          = 0x0,
+    /* reserved bits */
+    AUDIO_DEVICE_BIT_IN                        = 0x80000000,
+    AUDIO_DEVICE_BIT_DEFAULT                   = 0x40000000,
+    /* output devices */
+    AUDIO_DEVICE_OUT_EARPIECE                  = 0x1,
+    AUDIO_DEVICE_OUT_SPEAKER                   = 0x2,
+    AUDIO_DEVICE_OUT_WIRED_HEADSET             = 0x4,
+    AUDIO_DEVICE_OUT_WIRED_HEADPHONE           = 0x8,
+    AUDIO_DEVICE_OUT_BLUETOOTH_SCO             = 0x10,
+    AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET     = 0x20,
+    AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT      = 0x40,
+    AUDIO_DEVICE_OUT_BLUETOOTH_A2DP            = 0x80,
+    AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES = 0x100,
+    AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER    = 0x200,
+    AUDIO_DEVICE_OUT_AUX_DIGITAL               = 0x400,
+    AUDIO_DEVICE_OUT_HDMI                      = AUDIO_DEVICE_OUT_AUX_DIGITAL,
+    /* uses an analog connection (multiplexed over the USB connector pins for instance) */
+    AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET         = 0x800,
+    AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET         = 0x1000,
+    /* USB accessory mode: your Android device is a USB device and the dock is a USB host */
+    AUDIO_DEVICE_OUT_USB_ACCESSORY             = 0x2000,
+    /* USB host mode: your Android device is a USB host and the dock is a USB device */
+    AUDIO_DEVICE_OUT_USB_DEVICE                = 0x4000,
+    AUDIO_DEVICE_OUT_REMOTE_SUBMIX             = 0x8000,
+    /* Telephony voice TX path */
+    AUDIO_DEVICE_OUT_TELEPHONY_TX              = 0x10000,
+    /* Analog jack with line impedance detected */
+    AUDIO_DEVICE_OUT_LINE                      = 0x20000,
+    /* HDMI Audio Return Channel */
+    AUDIO_DEVICE_OUT_HDMI_ARC                  = 0x40000,
+    /* S/PDIF out */
+    AUDIO_DEVICE_OUT_SPDIF                     = 0x80000,
+    /* FM transmitter out */
+    AUDIO_DEVICE_OUT_FM                        = 0x100000,
+    AUDIO_DEVICE_OUT_DEFAULT                   = AUDIO_DEVICE_BIT_DEFAULT,
+    AUDIO_DEVICE_OUT_ALL      = (AUDIO_DEVICE_OUT_EARPIECE |
+                                 AUDIO_DEVICE_OUT_SPEAKER |
+                                 AUDIO_DEVICE_OUT_WIRED_HEADSET |
+                                 AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
+                                 AUDIO_DEVICE_OUT_BLUETOOTH_SCO |
+                                 AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET |
+                                 AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT |
+                                 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP |
+                                 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
+                                 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER |
+                                 AUDIO_DEVICE_OUT_HDMI |
+                                 AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET |
+                                 AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET |
+                                 AUDIO_DEVICE_OUT_USB_ACCESSORY |
+                                 AUDIO_DEVICE_OUT_USB_DEVICE |
+                                 AUDIO_DEVICE_OUT_REMOTE_SUBMIX |
+                                 AUDIO_DEVICE_OUT_TELEPHONY_TX |
+                                 AUDIO_DEVICE_OUT_LINE |
+                                 AUDIO_DEVICE_OUT_HDMI_ARC |
+                                 AUDIO_DEVICE_OUT_SPDIF |
+                                 AUDIO_DEVICE_OUT_FM |
+                                 AUDIO_DEVICE_OUT_DEFAULT),
+    AUDIO_DEVICE_OUT_ALL_A2DP = (AUDIO_DEVICE_OUT_BLUETOOTH_A2DP |
+                                 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
+                                 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER),
+    AUDIO_DEVICE_OUT_ALL_SCO  = (AUDIO_DEVICE_OUT_BLUETOOTH_SCO |
+                                 AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET |
+                                 AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT),
+    AUDIO_DEVICE_OUT_ALL_USB  = (AUDIO_DEVICE_OUT_USB_ACCESSORY |
+                                 AUDIO_DEVICE_OUT_USB_DEVICE),
+
+    /* input devices */
+    AUDIO_DEVICE_IN_COMMUNICATION         = AUDIO_DEVICE_BIT_IN | 0x1,
+    AUDIO_DEVICE_IN_AMBIENT               = AUDIO_DEVICE_BIT_IN | 0x2,
+    AUDIO_DEVICE_IN_BUILTIN_MIC           = AUDIO_DEVICE_BIT_IN | 0x4,
+    AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET = AUDIO_DEVICE_BIT_IN | 0x8,
+    AUDIO_DEVICE_IN_WIRED_HEADSET         = AUDIO_DEVICE_BIT_IN | 0x10,
+    AUDIO_DEVICE_IN_AUX_DIGITAL           = AUDIO_DEVICE_BIT_IN | 0x20,
+    AUDIO_DEVICE_IN_HDMI                  = AUDIO_DEVICE_IN_AUX_DIGITAL,
+    /* Telephony voice RX path */
+    AUDIO_DEVICE_IN_VOICE_CALL            = AUDIO_DEVICE_BIT_IN | 0x40,
+    AUDIO_DEVICE_IN_TELEPHONY_RX          = AUDIO_DEVICE_IN_VOICE_CALL,
+    AUDIO_DEVICE_IN_BACK_MIC              = AUDIO_DEVICE_BIT_IN | 0x80,
+    AUDIO_DEVICE_IN_REMOTE_SUBMIX         = AUDIO_DEVICE_BIT_IN | 0x100,
+    AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET     = AUDIO_DEVICE_BIT_IN | 0x200,
+    AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET     = AUDIO_DEVICE_BIT_IN | 0x400,
+    AUDIO_DEVICE_IN_USB_ACCESSORY         = AUDIO_DEVICE_BIT_IN | 0x800,
+    AUDIO_DEVICE_IN_USB_DEVICE            = AUDIO_DEVICE_BIT_IN | 0x1000,
+    /* FM tuner input */
+    AUDIO_DEVICE_IN_FM_TUNER              = AUDIO_DEVICE_BIT_IN | 0x2000,
+    /* TV tuner input */
+    AUDIO_DEVICE_IN_TV_TUNER              = AUDIO_DEVICE_BIT_IN | 0x4000,
+    /* Analog jack with line impedance detected */
+    AUDIO_DEVICE_IN_LINE                  = AUDIO_DEVICE_BIT_IN | 0x8000,
+    /* S/PDIF in */
+    AUDIO_DEVICE_IN_SPDIF                 = AUDIO_DEVICE_BIT_IN | 0x10000,
+    AUDIO_DEVICE_IN_BLUETOOTH_A2DP        = AUDIO_DEVICE_BIT_IN | 0x20000,
+    AUDIO_DEVICE_IN_DEFAULT               = AUDIO_DEVICE_BIT_IN | AUDIO_DEVICE_BIT_DEFAULT,
+
+    AUDIO_DEVICE_IN_ALL     = (AUDIO_DEVICE_IN_COMMUNICATION |
+                               AUDIO_DEVICE_IN_AMBIENT |
+                               AUDIO_DEVICE_IN_BUILTIN_MIC |
+                               AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET |
+                               AUDIO_DEVICE_IN_WIRED_HEADSET |
+                               AUDIO_DEVICE_IN_HDMI |
+                               AUDIO_DEVICE_IN_TELEPHONY_RX |
+                               AUDIO_DEVICE_IN_BACK_MIC |
+                               AUDIO_DEVICE_IN_REMOTE_SUBMIX |
+                               AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET |
+                               AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET |
+                               AUDIO_DEVICE_IN_USB_ACCESSORY |
+                               AUDIO_DEVICE_IN_USB_DEVICE |
+                               AUDIO_DEVICE_IN_FM_TUNER |
+                               AUDIO_DEVICE_IN_TV_TUNER |
+                               AUDIO_DEVICE_IN_LINE |
+                               AUDIO_DEVICE_IN_SPDIF |
+                               AUDIO_DEVICE_IN_BLUETOOTH_A2DP |
+                               AUDIO_DEVICE_IN_DEFAULT),
+    AUDIO_DEVICE_IN_ALL_SCO = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET,
+    AUDIO_DEVICE_IN_ALL_USB  = (AUDIO_DEVICE_IN_USB_ACCESSORY |
+                                AUDIO_DEVICE_IN_USB_DEVICE),
+};
+
+typedef uint32_t audio_devices_t;
+
+/* the audio output flags serve two purposes:
+ * - when an AudioTrack is created they indicate a "wish" to be connected to an
+ * output stream with attributes corresponding to the specified flags
+ * - when present in an output profile descriptor listed for a particular audio
+ * hardware module, they indicate that an output stream can be opened that
+ * supports the attributes indicated by the flags.
+ * the audio policy manager will try to match the flags in the request
+ * (when getOuput() is called) to an available output stream.
+ */
+typedef enum {
+    AUDIO_OUTPUT_FLAG_NONE = 0x0,       // no attributes
+    AUDIO_OUTPUT_FLAG_DIRECT = 0x1,     // this output directly connects a track
+                                        // to one output stream: no software mixer
+    AUDIO_OUTPUT_FLAG_PRIMARY = 0x2,    // this output is the primary output of
+                                        // the device. It is unique and must be
+                                        // present. It is opened by default and
+                                        // receives routing, audio mode and volume
+                                        // controls related to voice calls.
+    AUDIO_OUTPUT_FLAG_FAST = 0x4,       // output supports "fast tracks",
+                                        // defined elsewhere
+    AUDIO_OUTPUT_FLAG_DEEP_BUFFER = 0x8, // use deep audio buffers
+    AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD = 0x10,  // offload playback of compressed
+                                                // streams to hardware codec
+    AUDIO_OUTPUT_FLAG_NON_BLOCKING = 0x20 // use non-blocking write
+} audio_output_flags_t;
+
+/* The audio input flags are analogous to audio output flags.
+ * Currently they are used only when an AudioRecord is created,
+ * to indicate a preference to be connected to an input stream with
+ * attributes corresponding to the specified flags.
+ */
+typedef enum {
+    AUDIO_INPUT_FLAG_NONE = 0x0,        // no attributes
+    AUDIO_INPUT_FLAG_FAST = 0x1,        // prefer an input that supports "fast tracks"
+} audio_input_flags_t;
+
+/* Additional information about compressed streams offloaded to
+ * hardware playback
+ * The version and size fields must be initialized by the caller by using
+ * one of the constants defined here.
+ */
+typedef struct {
+    uint16_t version;                   // version of the info structure
+    uint16_t size;                      // total size of the structure including version and size
+    uint32_t sample_rate;               // sample rate in Hz
+    audio_channel_mask_t channel_mask;  // channel mask
+    audio_format_t format;              // audio format
+    audio_stream_type_t stream_type;    // stream type
+    uint32_t bit_rate;                  // bit rate in bits per second
+    int64_t duration_us;                // duration in microseconds, -1 if unknown
+    bool has_video;                     // true if stream is tied to a video stream
+    bool is_streaming;                  // true if streaming, false if local playback
+} audio_offload_info_t;
+
+#define AUDIO_MAKE_OFFLOAD_INFO_VERSION(maj,min) \
+            ((((maj) & 0xff) << 8) | ((min) & 0xff))
+
+#define AUDIO_OFFLOAD_INFO_VERSION_0_1 AUDIO_MAKE_OFFLOAD_INFO_VERSION(0, 1)
+#define AUDIO_OFFLOAD_INFO_VERSION_CURRENT AUDIO_OFFLOAD_INFO_VERSION_0_1
+
+static const audio_offload_info_t AUDIO_INFO_INITIALIZER = {
+    version: AUDIO_OFFLOAD_INFO_VERSION_CURRENT,
+    size: sizeof(audio_offload_info_t),
+    sample_rate: 0,
+    channel_mask: 0,
+    format: AUDIO_FORMAT_DEFAULT,
+    stream_type: AUDIO_STREAM_VOICE_CALL,
+    bit_rate: 0,
+    duration_us: 0,
+    has_video: false,
+    is_streaming: false
+};
+
+
+/* audio hw module handle functions or structures referencing a module */
+typedef int audio_module_handle_t;
+
+/******************************
+ *  Volume control
+ *****************************/
+
+/* If the audio hardware supports gain control on some audio paths,
+ * the platform can expose them in the audio_policy.conf file. The audio HAL
+ * will then implement gain control functions that will use the following data
+ * structures. */
+
+/* Type of gain control exposed by an audio port */
+#define AUDIO_GAIN_MODE_JOINT     0x1 /* supports joint channel gain control */
+#define AUDIO_GAIN_MODE_CHANNELS  0x2 /* supports separate channel gain control */
+#define AUDIO_GAIN_MODE_RAMP      0x4 /* supports gain ramps */
+
+typedef uint32_t audio_gain_mode_t;
+
+
+/* An audio_gain struct is a representation of a gain stage.
+ * A gain stage is always attached to an audio port. */
+struct audio_gain  {
+    audio_gain_mode_t    mode;          /* e.g. AUDIO_GAIN_MODE_JOINT */
+    audio_channel_mask_t channel_mask;  /* channels which gain an be controlled.
+                                           N/A if AUDIO_GAIN_MODE_CHANNELS is not supported */
+    int                  min_value;     /* minimum gain value in millibels */
+    int                  max_value;     /* maximum gain value in millibels */
+    int                  default_value; /* default gain value in millibels */
+    unsigned int         step_value;    /* gain step in millibels */
+    unsigned int         min_ramp_ms;   /* minimum ramp duration in ms */
+    unsigned int         max_ramp_ms;   /* maximum ramp duration in ms */
+};
+
+/* The gain configuration structure is used to get or set the gain values of a
+ * given port */
+struct audio_gain_config  {
+    int                  index;             /* index of the corresponding audio_gain in the
+                                               audio_port gains[] table */
+    audio_gain_mode_t    mode;              /* mode requested for this command */
+    audio_channel_mask_t channel_mask;      /* channels which gain value follows.
+                                               N/A in joint mode */
+    int                  values[sizeof(audio_channel_mask_t)]; /* gain values in millibels for each
+                                               channel ordered from LSb to MSb in channel mask.
+                                               The number of values is 1 in joint mode or
+                                               popcount(channel_mask) */
+    unsigned int         ramp_duration_ms; /* ramp duration in ms */
+};
+
+/******************************
+ *  Routing control
+ *****************************/
+
+/* Types defined here are used to describe an audio source or sink at internal
+ * framework interfaces (audio policy, patch panel) or at the audio HAL.
+ * Sink and sources are grouped in a concept of “audio port” representing an
+ * audio end point at the edge of the system managed by the module exposing
+ * the interface. */
+
+/* Audio port role: either source or sink */
+typedef enum {
+    AUDIO_PORT_ROLE_NONE,
+    AUDIO_PORT_ROLE_SOURCE,
+    AUDIO_PORT_ROLE_SINK,
+} audio_port_role_t;
+
+/* Audio port type indicates if it is a session (e.g AudioTrack),
+ * a mix (e.g PlaybackThread output) or a physical device
+ * (e.g AUDIO_DEVICE_OUT_SPEAKER) */
+typedef enum {
+    AUDIO_PORT_TYPE_NONE,
+    AUDIO_PORT_TYPE_DEVICE,
+    AUDIO_PORT_TYPE_MIX,
+    AUDIO_PORT_TYPE_SESSION,
+} audio_port_type_t;
+
+/* Each port has a unique ID or handle allocated by policy manager */
+typedef int audio_port_handle_t;
+#define AUDIO_PORT_HANDLE_NONE 0
+
+
+/* maximum audio device address length */
+#define AUDIO_DEVICE_MAX_ADDRESS_LEN 32
+
+/* extension for audio port configuration structure when the audio port is a
+ * hardware device */
+struct audio_port_config_device_ext {
+    audio_module_handle_t hw_module;                /* module the device is attached to */
+    audio_devices_t       type;                     /* device type (e.g AUDIO_DEVICE_OUT_SPEAKER) */
+    char                  address[AUDIO_DEVICE_MAX_ADDRESS_LEN]; /* device address. "" if N/A */
+};
+
+/* extension for audio port configuration structure when the audio port is a
+ * sub mix */
+struct audio_port_config_mix_ext {
+    audio_module_handle_t hw_module;    /* module the stream is attached to */
+    audio_io_handle_t handle;           /* I/O handle of the input/output stream */
+    union {
+        //TODO: change use case for output streams: use strategy and mixer attributes
+        audio_stream_type_t stream;
+        audio_source_t      source;
+    } usecase;
+};
+
+/* extension for audio port configuration structure when the audio port is an
+ * audio session */
+struct audio_port_config_session_ext {
+    audio_session_t   session; /* audio session */
+};
+
+/* Flags indicating which fields are to be considered in struct audio_port_config */
+#define AUDIO_PORT_CONFIG_SAMPLE_RATE  0x1
+#define AUDIO_PORT_CONFIG_CHANNEL_MASK 0x2
+#define AUDIO_PORT_CONFIG_FORMAT       0x4
+#define AUDIO_PORT_CONFIG_GAIN         0x8
+#define AUDIO_PORT_CONFIG_ALL (AUDIO_PORT_CONFIG_SAMPLE_RATE | \
+                               AUDIO_PORT_CONFIG_CHANNEL_MASK | \
+                               AUDIO_PORT_CONFIG_FORMAT | \
+                               AUDIO_PORT_CONFIG_GAIN)
+
+/* audio port configuration structure used to specify a particular configuration of
+ * an audio port */
+struct audio_port_config {
+    audio_port_handle_t      id;           /* port unique ID */
+    audio_port_role_t        role;         /* sink or source */
+    audio_port_type_t        type;         /* device, mix ... */
+    unsigned int             config_mask;  /* e.g AUDIO_PORT_CONFIG_ALL */
+    unsigned int             sample_rate;  /* sampling rate in Hz */
+    audio_channel_mask_t     channel_mask; /* channel mask if applicable */
+    audio_format_t           format;       /* format if applicable */
+    struct audio_gain_config gain;         /* gain to apply if applicable */
+    union {
+        struct audio_port_config_device_ext  device;  /* device specific info */
+        struct audio_port_config_mix_ext     mix;     /* mix specific info */
+        struct audio_port_config_session_ext session; /* session specific info */
+    } ext;
+};
+
+
+/* max number of sampling rates in audio port */
+#define AUDIO_PORT_MAX_SAMPLING_RATES 16
+/* max number of channel masks in audio port */
+#define AUDIO_PORT_MAX_CHANNEL_MASKS 16
+/* max number of audio formats in audio port */
+#define AUDIO_PORT_MAX_FORMATS 16
+/* max number of gain controls in audio port */
+#define AUDIO_PORT_MAX_GAINS 16
+
+/* extension for audio port structure when the audio port is a hardware device */
+struct audio_port_device_ext {
+    audio_module_handle_t hw_module;    /* module the device is attached to */
+    audio_devices_t       type;         /* device type (e.g AUDIO_DEVICE_OUT_SPEAKER) */
+    char                  address[AUDIO_DEVICE_MAX_ADDRESS_LEN];
+};
+
+/* Latency class of the audio mix */
+typedef enum {
+    AUDIO_LATENCY_LOW,
+    AUDIO_LATENCY_NORMAL,
+} audio_mix_latency_class_t;
+
+/* extension for audio port structure when the audio port is a sub mix */
+struct audio_port_mix_ext {
+    audio_module_handle_t     hw_module;     /* module the stream is attached to */
+    audio_io_handle_t         handle;        /* I/O handle of the input.output stream */
+    audio_mix_latency_class_t latency_class; /* latency class */
+    // other attributes: routing strategies
+};
+
+/* extension for audio port structure when the audio port is an audio session */
+struct audio_port_session_ext {
+    audio_session_t   session; /* audio session */
+};
+
+
+struct audio_port {
+    audio_port_handle_t      id;                /* port unique ID */
+    audio_port_role_t        role;              /* sink or source */
+    audio_port_type_t        type;              /* device, mix ... */
+    unsigned int             num_sample_rates;  /* number of sampling rates in following array */
+    unsigned int             sample_rates[AUDIO_PORT_MAX_SAMPLING_RATES];
+    unsigned int             num_channel_masks; /* number of channel masks in following array */
+    audio_channel_mask_t     channel_masks[AUDIO_PORT_MAX_CHANNEL_MASKS];
+    unsigned int             num_formats;       /* number of formats in following array */
+    audio_format_t           formats[AUDIO_PORT_MAX_FORMATS];
+    unsigned int             num_gains;         /* number of gains in following array */
+    struct audio_gain        gains[AUDIO_PORT_MAX_GAINS];
+    struct audio_port_config active_config;     /* current audio port configuration */
+    union {
+        struct audio_port_device_ext  device;
+        struct audio_port_mix_ext     mix;
+        struct audio_port_session_ext session;
+    } ext;
+};
+
+/* An audio patch represents a connection between one or more source ports and
+ * one or more sink ports. Patches are connected and disconnected by audio policy manager or by
+ * applications via framework APIs.
+ * Each patch is identified by a handle at the interface used to create that patch. For instance,
+ * when a patch is created by the audio HAL, the HAL allocates and returns a handle.
+ * This handle is unique to a given audio HAL hardware module.
+ * But the same patch receives another system wide unique handle allocated by the framework.
+ * This unique handle is used for all transactions inside the framework.
+ */
+typedef int audio_patch_handle_t;
+#define AUDIO_PATCH_HANDLE_NONE 0
+
+#define AUDIO_PATCH_PORTS_MAX   16
+
+struct audio_patch {
+    audio_patch_handle_t id;            /* patch unique ID */
+    unsigned int      num_sources;      /* number of sources in following array */
+    struct audio_port_config sources[AUDIO_PATCH_PORTS_MAX];
+    unsigned int      num_sinks;        /* number of sinks in following array */
+    struct audio_port_config sinks[AUDIO_PATCH_PORTS_MAX];
+};
+
+
+static inline bool audio_is_output_device(audio_devices_t device)
+{
+    if (((device & AUDIO_DEVICE_BIT_IN) == 0) &&
+            (popcount(device) == 1) && ((device & ~AUDIO_DEVICE_OUT_ALL) == 0))
+        return true;
+    else
+        return false;
+}
+
+static inline bool audio_is_input_device(audio_devices_t device)
+{
+    if ((device & AUDIO_DEVICE_BIT_IN) != 0) {
+        device &= ~AUDIO_DEVICE_BIT_IN;
+        if ((popcount(device) == 1) && ((device & ~AUDIO_DEVICE_IN_ALL) == 0))
+            return true;
+    }
+    return false;
+}
+
+static inline bool audio_is_output_devices(audio_devices_t device)
+{
+    return (device & AUDIO_DEVICE_BIT_IN) == 0;
+}
+
+static inline bool audio_is_a2dp_in_device(audio_devices_t device)
+{
+    if ((device & AUDIO_DEVICE_BIT_IN) != 0) {
+        device &= ~AUDIO_DEVICE_BIT_IN;
+        if ((popcount(device) == 1) && (device & AUDIO_DEVICE_IN_BLUETOOTH_A2DP))
+            return true;
+    }
+    return false;
+}
+
+static inline bool audio_is_a2dp_out_device(audio_devices_t device)
+{
+    if ((popcount(device) == 1) && (device & AUDIO_DEVICE_OUT_ALL_A2DP))
+        return true;
+    else
+        return false;
+}
+
+// Deprecated - use audio_is_a2dp_out_device() instead
+static inline bool audio_is_a2dp_device(audio_devices_t device)
+{
+    return audio_is_a2dp_out_device(device);
+}
+
+static inline bool audio_is_bluetooth_sco_device(audio_devices_t device)
+{
+    if ((device & AUDIO_DEVICE_BIT_IN) == 0) {
+        if ((popcount(device) == 1) && ((device & ~AUDIO_DEVICE_OUT_ALL_SCO) == 0))
+            return true;
+    } else {
+        device &= ~AUDIO_DEVICE_BIT_IN;
+        if ((popcount(device) == 1) && ((device & ~AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) == 0))
+            return true;
+    }
+
+    return false;
+}
+
+static inline bool audio_is_usb_out_device(audio_devices_t device)
+{
+    return ((popcount(device) == 1) && (device & AUDIO_DEVICE_OUT_ALL_USB));
+}
+
+static inline bool audio_is_usb_in_device(audio_devices_t device)
+{
+    if ((device & AUDIO_DEVICE_BIT_IN) != 0) {
+        device &= ~AUDIO_DEVICE_BIT_IN;
+        if (popcount(device) == 1 && (device & AUDIO_DEVICE_IN_ALL_USB) != 0)
+            return true;
+    }
+    return false;
+}
+
+/* OBSOLETE - use audio_is_usb_out_device() instead. */
+static inline bool audio_is_usb_device(audio_devices_t device)
+{
+    return audio_is_usb_out_device(device);
+}
+
+static inline bool audio_is_remote_submix_device(audio_devices_t device)
+{
+    if ((device & AUDIO_DEVICE_OUT_REMOTE_SUBMIX) == AUDIO_DEVICE_OUT_REMOTE_SUBMIX
+            || (device & AUDIO_DEVICE_IN_REMOTE_SUBMIX) == AUDIO_DEVICE_IN_REMOTE_SUBMIX)
+        return true;
+    else
+        return false;
+}
+
+static inline bool audio_is_input_channel(audio_channel_mask_t channel)
+{
+    if ((channel & ~AUDIO_CHANNEL_IN_ALL) == 0)
+        return channel != 0;
+    else
+        return false;
+}
+
+static inline bool audio_is_output_channel(audio_channel_mask_t channel)
+{
+    if ((channel & ~AUDIO_CHANNEL_OUT_ALL) == 0)
+        return channel != 0;
+    else
+        return false;
+}
+
+/* Returns the number of channels from an input channel mask,
+ * used in the context of audio input or recording.
+ */
+static inline uint32_t audio_channel_count_from_in_mask(audio_channel_mask_t channel)
+{
+    return popcount(channel & AUDIO_CHANNEL_IN_ALL);
+}
+
+/* Returns the number of channels from an output channel mask,
+ * used in the context of audio output or playback.
+ */
+static inline uint32_t audio_channel_count_from_out_mask(audio_channel_mask_t channel)
+{
+    return popcount(channel & AUDIO_CHANNEL_OUT_ALL);
+}
+
+/* Derive an output channel mask from a channel count.
+ * This is to be used when the content channel mask is unknown. The 1, 2, 4, 5, 6, 7 and 8 channel
+ * cases are mapped to the standard game/home-theater layouts, but note that 4 is mapped to quad,
+ * and not stereo + FC + mono surround. A channel count of 3 is arbitrarily mapped to stereo + FC
+ * for continuity with stereo.
+ * Returns the matching channel mask, or 0 if the number of channels exceeds that of the
+ * configurations for which a default channel mask is defined.
+ */
+static inline audio_channel_mask_t audio_channel_out_mask_from_count(uint32_t channel_count)
+{
+    switch (channel_count) {
+    case 1:
+        return AUDIO_CHANNEL_OUT_MONO;
+    case 2:
+        return AUDIO_CHANNEL_OUT_STEREO;
+    case 3:
+        return (AUDIO_CHANNEL_OUT_STEREO | AUDIO_CHANNEL_OUT_FRONT_CENTER);
+    case 4: // 4.0
+        return AUDIO_CHANNEL_OUT_QUAD;
+    case 5: // 5.0
+        return (AUDIO_CHANNEL_OUT_QUAD | AUDIO_CHANNEL_OUT_FRONT_CENTER);
+    case 6: // 5.1
+        return AUDIO_CHANNEL_OUT_5POINT1;
+    case 7: // 6.1
+        return (AUDIO_CHANNEL_OUT_5POINT1 | AUDIO_CHANNEL_OUT_BACK_CENTER);
+    case 8:
+        return AUDIO_CHANNEL_OUT_7POINT1;
+    default:
+        return 0;
+    }
+}
+
+/* Similar to above, but for input.  Currently handles only mono and stereo. */
+static inline audio_channel_mask_t audio_channel_in_mask_from_count(uint32_t channel_count)
+{
+    switch (channel_count) {
+    case 1:
+        return AUDIO_CHANNEL_IN_MONO;
+    case 2:
+        return AUDIO_CHANNEL_IN_STEREO;
+    default:
+        return 0;
+    }
+}
+
+static inline bool audio_is_valid_format(audio_format_t format)
+{
+    switch (format & AUDIO_FORMAT_MAIN_MASK) {
+    case AUDIO_FORMAT_PCM:
+        switch (format) {
+        case AUDIO_FORMAT_PCM_16_BIT:
+        case AUDIO_FORMAT_PCM_8_BIT:
+        case AUDIO_FORMAT_PCM_32_BIT:
+        case AUDIO_FORMAT_PCM_8_24_BIT:
+        case AUDIO_FORMAT_PCM_FLOAT:
+        case AUDIO_FORMAT_PCM_24_BIT_PACKED:
+            return true;
+        default:
+            return false;
+        }
+        /* not reached */
+    case AUDIO_FORMAT_MP3:
+    case AUDIO_FORMAT_AMR_NB:
+    case AUDIO_FORMAT_AMR_WB:
+    case AUDIO_FORMAT_AAC:
+    case AUDIO_FORMAT_HE_AAC_V1:
+    case AUDIO_FORMAT_HE_AAC_V2:
+    case AUDIO_FORMAT_VORBIS:
+    case AUDIO_FORMAT_OPUS:
+    case AUDIO_FORMAT_AC3:
+    case AUDIO_FORMAT_E_AC3:
+        return true;
+    default:
+        return false;
+    }
+}
+
+static inline bool audio_is_linear_pcm(audio_format_t format)
+{
+    return ((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM);
+}
+
+static inline size_t audio_bytes_per_sample(audio_format_t format)
+{
+    size_t size = 0;
+
+    switch (format) {
+    case AUDIO_FORMAT_PCM_32_BIT:
+    case AUDIO_FORMAT_PCM_8_24_BIT:
+        size = sizeof(int32_t);
+        break;
+    case AUDIO_FORMAT_PCM_24_BIT_PACKED:
+        size = sizeof(uint8_t) * 3;
+        break;
+    case AUDIO_FORMAT_PCM_16_BIT:
+        size = sizeof(int16_t);
+        break;
+    case AUDIO_FORMAT_PCM_8_BIT:
+        size = sizeof(uint8_t);
+        break;
+    case AUDIO_FORMAT_PCM_FLOAT:
+        size = sizeof(float);
+        break;
+    default:
+        break;
+    }
+    return size;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  // ANDROID_AUDIO_CORE_H
diff --git a/package/utils/adbd/src/include/system/audio_policy.h b/package/utils/adbd/src/include/system/audio_policy.h
new file mode 100644
index 0000000..f805cdc
--- /dev/null
+++ b/package/utils/adbd/src/include/system/audio_policy.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2011 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 ANDROID_AUDIO_POLICY_CORE_H
+#define ANDROID_AUDIO_POLICY_CORE_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <cutils/bitops.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/* The enums were moved here mostly from
+ * frameworks/base/include/media/AudioSystem.h
+ */
+
+/* device categories used for audio_policy->set_force_use() */
+typedef enum {
+    AUDIO_POLICY_FORCE_NONE,
+    AUDIO_POLICY_FORCE_SPEAKER,
+    AUDIO_POLICY_FORCE_HEADPHONES,
+    AUDIO_POLICY_FORCE_BT_SCO,
+    AUDIO_POLICY_FORCE_BT_A2DP,
+    AUDIO_POLICY_FORCE_WIRED_ACCESSORY,
+    AUDIO_POLICY_FORCE_BT_CAR_DOCK,
+    AUDIO_POLICY_FORCE_BT_DESK_DOCK,
+    AUDIO_POLICY_FORCE_ANALOG_DOCK,
+    AUDIO_POLICY_FORCE_DIGITAL_DOCK,
+    AUDIO_POLICY_FORCE_NO_BT_A2DP, /* A2DP sink is not preferred to speaker or wired HS */
+    AUDIO_POLICY_FORCE_SYSTEM_ENFORCED,
+
+    AUDIO_POLICY_FORCE_CFG_CNT,
+    AUDIO_POLICY_FORCE_CFG_MAX = AUDIO_POLICY_FORCE_CFG_CNT - 1,
+
+    AUDIO_POLICY_FORCE_DEFAULT = AUDIO_POLICY_FORCE_NONE,
+} audio_policy_forced_cfg_t;
+
+/* usages used for audio_policy->set_force_use() */
+typedef enum {
+    AUDIO_POLICY_FORCE_FOR_COMMUNICATION,
+    AUDIO_POLICY_FORCE_FOR_MEDIA,
+    AUDIO_POLICY_FORCE_FOR_RECORD,
+    AUDIO_POLICY_FORCE_FOR_DOCK,
+    AUDIO_POLICY_FORCE_FOR_SYSTEM,
+
+    AUDIO_POLICY_FORCE_USE_CNT,
+    AUDIO_POLICY_FORCE_USE_MAX = AUDIO_POLICY_FORCE_USE_CNT - 1,
+} audio_policy_force_use_t;
+
+/* device connection states used for audio_policy->set_device_connection_state()
+ */
+typedef enum {
+    AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
+    AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
+
+    AUDIO_POLICY_DEVICE_STATE_CNT,
+    AUDIO_POLICY_DEVICE_STATE_MAX = AUDIO_POLICY_DEVICE_STATE_CNT - 1,
+} audio_policy_dev_state_t;
+
+typedef enum {
+    /* Used to generate a tone to notify the user of a
+     * notification/alarm/ringtone while they are in a call. */
+    AUDIO_POLICY_TONE_IN_CALL_NOTIFICATION = 0,
+
+    AUDIO_POLICY_TONE_CNT,
+    AUDIO_POLICY_TONE_MAX                  = AUDIO_POLICY_TONE_CNT - 1,
+} audio_policy_tone_t;
+
+
+static inline bool audio_is_low_visibility(audio_stream_type_t stream)
+{
+    switch (stream) {
+    case AUDIO_STREAM_SYSTEM:
+    case AUDIO_STREAM_NOTIFICATION:
+    case AUDIO_STREAM_RING:
+        return true;
+    default:
+        return false;
+    }
+}
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  // ANDROID_AUDIO_POLICY_CORE_H
diff --git a/package/utils/adbd/src/include/system/camera.h b/package/utils/adbd/src/include/system/camera.h
new file mode 100644
index 0000000..c676201
--- /dev/null
+++ b/package/utils/adbd/src/include/system/camera.h
@@ -0,0 +1,279 @@
+/*
+ * Copyright (C) 2011 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 SYSTEM_CORE_INCLUDE_ANDROID_CAMERA_H
+#define SYSTEM_CORE_INCLUDE_ANDROID_CAMERA_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <cutils/native_handle.h>
+#include <hardware/hardware.h>
+#include <hardware/gralloc.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * A set of bit masks for specifying how the received preview frames are
+ * handled before the previewCallback() call.
+ *
+ * The least significant 3 bits of an "int" value are used for this purpose:
+ *
+ * ..... 0 0 0
+ *       ^ ^ ^
+ *       | | |---------> determine whether the callback is enabled or not
+ *       | |-----------> determine whether the callback is one-shot or not
+ *       |-------------> determine whether the frame is copied out or not
+ *
+ * WARNING: When a frame is sent directly without copying, it is the frame
+ * receiver's responsiblity to make sure that the frame data won't get
+ * corrupted by subsequent preview frames filled by the camera. This flag is
+ * recommended only when copying out data brings significant performance price
+ * and the handling/processing of the received frame data is always faster than
+ * the preview frame rate so that data corruption won't occur.
+ *
+ * For instance,
+ * 1. 0x00 disables the callback. In this case, copy out and one shot bits
+ *    are ignored.
+ * 2. 0x01 enables a callback without copying out the received frames. A
+ *    typical use case is the Camcorder application to avoid making costly
+ *    frame copies.
+ * 3. 0x05 is enabling a callback with frame copied out repeatedly. A typical
+ *    use case is the Camera application.
+ * 4. 0x07 is enabling a callback with frame copied out only once. A typical
+ *    use case is the Barcode scanner application.
+ */
+
+enum {
+    CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK = 0x01,
+    CAMERA_FRAME_CALLBACK_FLAG_ONE_SHOT_MASK = 0x02,
+    CAMERA_FRAME_CALLBACK_FLAG_COPY_OUT_MASK = 0x04,
+    /** Typical use cases */
+    CAMERA_FRAME_CALLBACK_FLAG_NOOP = 0x00,
+    CAMERA_FRAME_CALLBACK_FLAG_CAMCORDER = 0x01,
+    CAMERA_FRAME_CALLBACK_FLAG_CAMERA = 0x05,
+    CAMERA_FRAME_CALLBACK_FLAG_BARCODE_SCANNER = 0x07
+};
+
+/** msgType in notifyCallback and dataCallback functions */
+enum {
+    CAMERA_MSG_ERROR = 0x0001,            // notifyCallback
+    CAMERA_MSG_SHUTTER = 0x0002,          // notifyCallback
+    CAMERA_MSG_FOCUS = 0x0004,            // notifyCallback
+    CAMERA_MSG_ZOOM = 0x0008,             // notifyCallback
+    CAMERA_MSG_PREVIEW_FRAME = 0x0010,    // dataCallback
+    CAMERA_MSG_VIDEO_FRAME = 0x0020,      // data_timestamp_callback
+    CAMERA_MSG_POSTVIEW_FRAME = 0x0040,   // dataCallback
+    CAMERA_MSG_RAW_IMAGE = 0x0080,        // dataCallback
+    CAMERA_MSG_COMPRESSED_IMAGE = 0x0100, // dataCallback
+    CAMERA_MSG_RAW_IMAGE_NOTIFY = 0x0200, // dataCallback
+    // Preview frame metadata. This can be combined with
+    // CAMERA_MSG_PREVIEW_FRAME in dataCallback. For example, the apps can
+    // request FRAME and METADATA. Or the apps can request only FRAME or only
+    // METADATA.
+    CAMERA_MSG_PREVIEW_METADATA = 0x0400, // dataCallback
+    // Notify on autofocus start and stop. This is useful in continuous
+    // autofocus - FOCUS_MODE_CONTINUOUS_VIDEO and FOCUS_MODE_CONTINUOUS_PICTURE.
+    CAMERA_MSG_FOCUS_MOVE = 0x0800,       // notifyCallback
+    CAMERA_MSG_ALL_MSGS = 0xFFFF
+};
+
+/** cmdType in sendCommand functions */
+enum {
+    CAMERA_CMD_START_SMOOTH_ZOOM = 1,
+    CAMERA_CMD_STOP_SMOOTH_ZOOM = 2,
+
+    /**
+     * Set the clockwise rotation of preview display (setPreviewDisplay) in
+     * degrees. This affects the preview frames and the picture displayed after
+     * snapshot. This method is useful for portrait mode applications. Note
+     * that preview display of front-facing cameras is flipped horizontally
+     * before the rotation, that is, the image is reflected along the central
+     * vertical axis of the camera sensor. So the users can see themselves as
+     * looking into a mirror.
+     *
+     * This does not affect the order of byte array of
+     * CAMERA_MSG_PREVIEW_FRAME, CAMERA_MSG_VIDEO_FRAME,
+     * CAMERA_MSG_POSTVIEW_FRAME, CAMERA_MSG_RAW_IMAGE, or
+     * CAMERA_MSG_COMPRESSED_IMAGE. This is allowed to be set during preview
+     * since API level 14.
+     */
+    CAMERA_CMD_SET_DISPLAY_ORIENTATION = 3,
+
+    /**
+     * cmdType to disable/enable shutter sound. In sendCommand passing arg1 =
+     * 0 will disable, while passing arg1 = 1 will enable the shutter sound.
+     */
+    CAMERA_CMD_ENABLE_SHUTTER_SOUND = 4,
+
+    /* cmdType to play recording sound */
+    CAMERA_CMD_PLAY_RECORDING_SOUND = 5,
+
+    /**
+     * Start the face detection. This should be called after preview is started.
+     * The camera will notify the listener of CAMERA_MSG_FACE and the detected
+     * faces in the preview frame. The detected faces may be the same as the
+     * previous ones. Apps should call CAMERA_CMD_STOP_FACE_DETECTION to stop
+     * the face detection. This method is supported if CameraParameters
+     * KEY_MAX_NUM_HW_DETECTED_FACES or KEY_MAX_NUM_SW_DETECTED_FACES is
+     * bigger than 0. Hardware and software face detection should not be running
+     * at the same time. If the face detection has started, apps should not send
+     * this again.
+     *
+     * In hardware face detection mode, CameraParameters KEY_WHITE_BALANCE,
+     * KEY_FOCUS_AREAS and KEY_METERING_AREAS have no effect.
+     *
+     * arg1 is the face detection type. It can be CAMERA_FACE_DETECTION_HW or
+     * CAMERA_FACE_DETECTION_SW. If the type of face detection requested is not
+     * supported, the HAL must return BAD_VALUE.
+     */
+    CAMERA_CMD_START_FACE_DETECTION = 6,
+
+    /**
+     * Stop the face detection.
+     */
+    CAMERA_CMD_STOP_FACE_DETECTION = 7,
+
+    /**
+     * Enable/disable focus move callback (CAMERA_MSG_FOCUS_MOVE). Passing
+     * arg1 = 0 will disable, while passing arg1 = 1 will enable the callback.
+     */
+    CAMERA_CMD_ENABLE_FOCUS_MOVE_MSG = 8,
+
+    /**
+     * Ping camera service to see if camera hardware is released.
+     *
+     * When any camera method returns error, the client can use ping command
+     * to see if the camera has been taken away by other clients. If the result
+     * is NO_ERROR, it means the camera hardware is not released. If the result
+     * is not NO_ERROR, the camera has been released and the existing client
+     * can silently finish itself or show a dialog.
+     */
+    CAMERA_CMD_PING = 9,
+
+    /**
+     * Configure the number of video buffers used for recording. The intended
+     * video buffer count for recording is passed as arg1, which must be
+     * greater than 0. This command must be sent before recording is started.
+     * This command returns INVALID_OPERATION error if it is sent after video
+     * recording is started, or the command is not supported at all. This
+     * command also returns a BAD_VALUE error if the intended video buffer
+     * count is non-positive or too big to be realized.
+     */
+    CAMERA_CMD_SET_VIDEO_BUFFER_COUNT = 10,
+};
+
+/** camera fatal errors */
+enum {
+    CAMERA_ERROR_UNKNOWN = 1,
+    /**
+     * Camera was released because another client has connected to the camera.
+     * The original client should call Camera::disconnect immediately after
+     * getting this notification. Otherwise, the camera will be released by
+     * camera service in a short time. The client should not call any method
+     * (except disconnect and sending CAMERA_CMD_PING) after getting this.
+     */
+    CAMERA_ERROR_RELEASED = 2,
+    CAMERA_ERROR_SERVER_DIED = 100
+};
+
+enum {
+    /** The facing of the camera is opposite to that of the screen. */
+    CAMERA_FACING_BACK = 0,
+    /** The facing of the camera is the same as that of the screen. */
+    CAMERA_FACING_FRONT = 1
+};
+
+enum {
+    /** Hardware face detection. It does not use much CPU. */
+    CAMERA_FACE_DETECTION_HW = 0,
+    /**
+     * Software face detection. It uses some CPU. Applications must use
+     * Camera.setPreviewTexture for preview in this mode.
+     */
+    CAMERA_FACE_DETECTION_SW = 1
+};
+
+/**
+ * The information of a face from camera face detection.
+ */
+typedef struct camera_face {
+    /**
+     * Bounds of the face [left, top, right, bottom]. (-1000, -1000) represents
+     * the top-left of the camera field of view, and (1000, 1000) represents the
+     * bottom-right of the field of view. The width and height cannot be 0 or
+     * negative. This is supported by both hardware and software face detection.
+     *
+     * The direction is relative to the sensor orientation, that is, what the
+     * sensor sees. The direction is not affected by the rotation or mirroring
+     * of CAMERA_CMD_SET_DISPLAY_ORIENTATION.
+     */
+    int32_t rect[4];
+
+    /**
+     * The confidence level of the face. The range is 1 to 100. 100 is the
+     * highest confidence. This is supported by both hardware and software
+     * face detection.
+     */
+    int32_t score;
+
+    /**
+     * An unique id per face while the face is visible to the tracker. If
+     * the face leaves the field-of-view and comes back, it will get a new
+     * id. If the value is 0, id is not supported.
+     */
+    int32_t id;
+
+    /**
+     * The coordinates of the center of the left eye. The range is -1000 to
+     * 1000. -2000, -2000 if this is not supported.
+     */
+    int32_t left_eye[2];
+
+    /**
+     * The coordinates of the center of the right eye. The range is -1000 to
+     * 1000. -2000, -2000 if this is not supported.
+     */
+    int32_t right_eye[2];
+
+    /**
+     * The coordinates of the center of the mouth. The range is -1000 to 1000.
+     * -2000, -2000 if this is not supported.
+     */
+    int32_t mouth[2];
+
+} camera_face_t;
+
+/**
+ * The metadata of the frame data.
+ */
+typedef struct camera_frame_metadata {
+    /**
+     * The number of detected faces in the frame.
+     */
+    int32_t number_of_faces;
+
+    /**
+     * An array of the detected faces. The length is number_of_faces.
+     */
+    camera_face_t *faces;
+} camera_frame_metadata_t;
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* SYSTEM_CORE_INCLUDE_ANDROID_CAMERA_H */
diff --git a/package/utils/adbd/src/include/system/graphics.h b/package/utils/adbd/src/include/system/graphics.h
new file mode 100644
index 0000000..74d790f
--- /dev/null
+++ b/package/utils/adbd/src/include/system/graphics.h
@@ -0,0 +1,509 @@
+/*
+ * Copyright (C) 2011 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 SYSTEM_CORE_INCLUDE_ANDROID_GRAPHICS_H
+#define SYSTEM_CORE_INCLUDE_ANDROID_GRAPHICS_H
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * If the HAL needs to create service threads to handle graphics related
+ * tasks, these threads need to run at HAL_PRIORITY_URGENT_DISPLAY priority
+ * if they can block the main rendering thread in any way.
+ *
+ * the priority of the current thread can be set with:
+ *
+ *      #include <sys/resource.h>
+ *      setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY);
+ *
+ */
+
+#define HAL_PRIORITY_URGENT_DISPLAY     (-8)
+
+/**
+ * pixel format definitions
+ */
+
+enum {
+    /*
+     * "linear" color pixel formats:
+     *
+     * The pixel formats below contain sRGB data but are otherwise treated
+     * as linear formats, i.e.: no special operation is performed when
+     * reading or writing into a buffer in one of these formats
+     */
+    HAL_PIXEL_FORMAT_RGBA_8888          = 1,
+    HAL_PIXEL_FORMAT_RGBX_8888          = 2,
+    HAL_PIXEL_FORMAT_RGB_888            = 3,
+    HAL_PIXEL_FORMAT_RGB_565            = 4,
+    HAL_PIXEL_FORMAT_BGRA_8888          = 5,
+
+    /*
+     * sRGB color pixel formats:
+     *
+     * The red, green and blue components are stored in sRGB space, and converted
+     * to linear space when read, using the standard sRGB to linear equation:
+     *
+     * Clinear = Csrgb / 12.92                  for Csrgb <= 0.04045
+     *         = (Csrgb + 0.055 / 1.055)^2.4    for Csrgb >  0.04045
+     *
+     * When written the inverse transformation is performed:
+     *
+     * Csrgb = 12.92 * Clinear                  for Clinear <= 0.0031308
+     *       = 1.055 * Clinear^(1/2.4) - 0.055  for Clinear >  0.0031308
+     *
+     *
+     *  The alpha component, if present, is always stored in linear space and
+     *  is left unmodified when read or written.
+     *
+     */
+    HAL_PIXEL_FORMAT_sRGB_A_8888        = 0xC,
+    HAL_PIXEL_FORMAT_sRGB_X_8888        = 0xD,
+
+    /*
+     * 0x100 - 0x1FF
+     *
+     * This range is reserved for pixel formats that are specific to the HAL
+     * implementation.  Implementations can use any value in this range to
+     * communicate video pixel formats between their HAL modules.  These formats
+     * must not have an alpha channel.  Additionally, an EGLimage created from a
+     * gralloc buffer of one of these formats must be supported for use with the
+     * GL_OES_EGL_image_external OpenGL ES extension.
+     */
+
+    /*
+     * Android YUV format:
+     *
+     * This format is exposed outside of the HAL to software decoders and
+     * applications.  EGLImageKHR must support it in conjunction with the
+     * OES_EGL_image_external extension.
+     *
+     * YV12 is a 4:2:0 YCrCb planar format comprised of a WxH Y plane followed
+     * by (W/2) x (H/2) Cr and Cb planes.
+     *
+     * This format assumes
+     * - an even width
+     * - an even height
+     * - a horizontal stride multiple of 16 pixels
+     * - a vertical stride equal to the height
+     *
+     *   y_size = stride * height
+     *   c_stride = ALIGN(stride/2, 16)
+     *   c_size = c_stride * height/2
+     *   size = y_size + c_size * 2
+     *   cr_offset = y_size
+     *   cb_offset = y_size + c_size
+     *
+     */
+    HAL_PIXEL_FORMAT_YV12   = 0x32315659, // YCrCb 4:2:0 Planar
+
+
+    /*
+     * Android Y8 format:
+     *
+     * This format is exposed outside of the HAL to the framework.
+     * The expected gralloc usage flags are SW_* and HW_CAMERA_*,
+     * and no other HW_ flags will be used.
+     *
+     * Y8 is a YUV planar format comprised of a WxH Y plane,
+     * with each pixel being represented by 8 bits.
+     *
+     * It is equivalent to just the Y plane from YV12.
+     *
+     * This format assumes
+     * - an even width
+     * - an even height
+     * - a horizontal stride multiple of 16 pixels
+     * - a vertical stride equal to the height
+     *
+     *   size = stride * height
+     *
+     */
+    HAL_PIXEL_FORMAT_Y8     = 0x20203859,
+
+    /*
+     * Android Y16 format:
+     *
+     * This format is exposed outside of the HAL to the framework.
+     * The expected gralloc usage flags are SW_* and HW_CAMERA_*,
+     * and no other HW_ flags will be used.
+     *
+     * Y16 is a YUV planar format comprised of a WxH Y plane,
+     * with each pixel being represented by 16 bits.
+     *
+     * It is just like Y8, but has double the bits per pixel (little endian).
+     *
+     * This format assumes
+     * - an even width
+     * - an even height
+     * - a horizontal stride multiple of 16 pixels
+     * - a vertical stride equal to the height
+     * - strides are specified in pixels, not in bytes
+     *
+     *   size = stride * height * 2
+     *
+     */
+    HAL_PIXEL_FORMAT_Y16    = 0x20363159,
+
+    /*
+     * Android RAW sensor format:
+     *
+     * This format is exposed outside of the camera HAL to applications.
+     *
+     * RAW_SENSOR is a single-channel, 16-bit, little endian  format, typically
+     * representing raw Bayer-pattern images from an image sensor, with minimal
+     * processing.
+     *
+     * The exact pixel layout of the data in the buffer is sensor-dependent, and
+     * needs to be queried from the camera device.
+     *
+     * Generally, not all 16 bits are used; more common values are 10 or 12
+     * bits. If not all bits are used, the lower-order bits are filled first.
+     * All parameters to interpret the raw data (black and white points,
+     * color space, etc) must be queried from the camera device.
+     *
+     * This format assumes
+     * - an even width
+     * - an even height
+     * - a horizontal stride multiple of 16 pixels
+     * - a vertical stride equal to the height
+     * - strides are specified in pixels, not in bytes
+     *
+     *   size = stride * height * 2
+     *
+     * This format must be accepted by the gralloc module when used with the
+     * following usage flags:
+     *    - GRALLOC_USAGE_HW_CAMERA_*
+     *    - GRALLOC_USAGE_SW_*
+     *    - GRALLOC_USAGE_RENDERSCRIPT
+     */
+    HAL_PIXEL_FORMAT_RAW16 = 0x20,
+    HAL_PIXEL_FORMAT_RAW_SENSOR = 0x20, // TODO(rubenbrunk): Remove RAW_SENSOR.
+
+    /*
+     * Android RAW10 format:
+     *
+     * This format is exposed outside of the camera HAL to applications.
+     *
+     * RAW10 is a single-channel, 10-bit per pixel, densely packed, unprocessed
+     * format, representing raw Bayer-pattern images coming from an image sensor.
+     *
+     * In an image buffer with this format, starting from the first pixel, each 4
+     * consecutive pixels are packed into 5 bytes (40 bits). Each one of the first
+     * 4 bytes contains the top 8 bits of each pixel, The fifth byte contains the
+     * 2 least significant bits of the 4 pixels, the exact layout data for each 4
+     * consecutive pixels is illustrated below (Pi[j] stands for the jth bit of
+     * the ith pixel):
+     *
+     *          bit 7                                     bit 0
+     *          =====|=====|=====|=====|=====|=====|=====|=====|
+     * Byte 0: |P0[9]|P0[8]|P0[7]|P0[6]|P0[5]|P0[4]|P0[3]|P0[2]|
+     *         |-----|-----|-----|-----|-----|-----|-----|-----|
+     * Byte 1: |P1[9]|P1[8]|P1[7]|P1[6]|P1[5]|P1[4]|P1[3]|P1[2]|
+     *         |-----|-----|-----|-----|-----|-----|-----|-----|
+     * Byte 2: |P2[9]|P2[8]|P2[7]|P2[6]|P2[5]|P2[4]|P2[3]|P2[2]|
+     *         |-----|-----|-----|-----|-----|-----|-----|-----|
+     * Byte 3: |P3[9]|P3[8]|P3[7]|P3[6]|P3[5]|P3[4]|P3[3]|P3[2]|
+     *         |-----|-----|-----|-----|-----|-----|-----|-----|
+     * Byte 4: |P3[1]|P3[0]|P2[1]|P2[0]|P1[1]|P1[0]|P0[1]|P0[0]|
+     *          ===============================================
+     *
+     * This format assumes
+     * - a width multiple of 4 pixels
+     * - an even height
+     * - a horizontal stride equal to the width
+     * - a vertical stride equal to the height
+     * - strides are specified in pixels, not in bytes
+     *
+     *   size = stride * height * 10 / 8
+     *
+     * This format must be accepted by the gralloc module when used with the
+     * following usage flags:
+     *    - GRALLOC_USAGE_HW_CAMERA_*
+     *    - GRALLOC_USAGE_SW_*
+     *    - GRALLOC_USAGE_RENDERSCRIPT
+     */
+    HAL_PIXEL_FORMAT_RAW10 = 0x25,
+
+    /*
+     * Android opaque RAW format:
+     *
+     * This format is exposed outside of the camera HAL to applications.
+     *
+     * RAW_OPAQUE is a format for unprocessed raw image buffers coming from an
+     * image sensor. The actual structure of buffers of this format is
+     * implementation-dependent.
+     *
+     * This format must be accepted by the gralloc module when used with the
+     * following usage flags:
+     *    - GRALLOC_USAGE_HW_CAMERA_*
+     *    - GRALLOC_USAGE_SW_*
+     *    - GRALLOC_USAGE_RENDERSCRIPT
+     */
+    HAL_PIXEL_FORMAT_RAW_OPAQUE = 0x24,
+
+    /*
+     * Android binary blob graphics buffer format:
+     *
+     * This format is used to carry task-specific data which does not have a
+     * standard image structure. The details of the format are left to the two
+     * endpoints.
+     *
+     * A typical use case is for transporting JPEG-compressed images from the
+     * Camera HAL to the framework or to applications.
+     *
+     * Buffers of this format must have a height of 1, and width equal to their
+     * size in bytes.
+     */
+    HAL_PIXEL_FORMAT_BLOB = 0x21,
+
+    /*
+     * Android format indicating that the choice of format is entirely up to the
+     * device-specific Gralloc implementation.
+     *
+     * The Gralloc implementation should examine the usage bits passed in when
+     * allocating a buffer with this format, and it should derive the pixel
+     * format from those usage flags.  This format will never be used with any
+     * of the GRALLOC_USAGE_SW_* usage flags.
+     *
+     * If a buffer of this format is to be used as an OpenGL ES texture, the
+     * framework will assume that sampling the texture will always return an
+     * alpha value of 1.0 (i.e. the buffer contains only opaque pixel values).
+     *
+     */
+    HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED = 0x22,
+
+    /*
+     * Android flexible YCbCr formats
+     *
+     * This format allows platforms to use an efficient YCbCr/YCrCb buffer
+     * layout, while still describing the buffer layout in a way accessible to
+     * the CPU in a device-independent manner.  While called YCbCr, it can be
+     * used to describe formats with either chromatic ordering, as well as
+     * whole planar or semiplanar layouts.
+     *
+     * struct android_ycbcr (below) is the the struct used to describe it.
+     *
+     * This format must be accepted by the gralloc module when
+     * USAGE_HW_CAMERA_WRITE and USAGE_SW_READ_* are set.
+     *
+     * This format is locked for use by gralloc's (*lock_ycbcr) method, and
+     * locking with the (*lock) method will return an error.
+     */
+    HAL_PIXEL_FORMAT_YCbCr_420_888 = 0x23,
+
+    /* Legacy formats (deprecated), used by ImageFormat.java */
+    HAL_PIXEL_FORMAT_YCbCr_422_SP       = 0x10, // NV16
+    HAL_PIXEL_FORMAT_YCrCb_420_SP       = 0x11, // NV21
+    HAL_PIXEL_FORMAT_YCbCr_422_I        = 0x14, // YUY2
+};
+
+/*
+ * Structure for describing YCbCr formats for consumption by applications.
+ * This is used with HAL_PIXEL_FORMAT_YCbCr_*_888.
+ *
+ * Buffer chroma subsampling is defined in the format.
+ * e.g. HAL_PIXEL_FORMAT_YCbCr_420_888 has subsampling 4:2:0.
+ *
+ * Buffers must have a 8 bit depth.
+ *
+ * @y, @cb, and @cr point to the first byte of their respective planes.
+ *
+ * Stride describes the distance in bytes from the first value of one row of
+ * the image to the first value of the next row.  It includes the width of the
+ * image plus padding.
+ * @ystride is the stride of the luma plane.
+ * @cstride is the stride of the chroma planes.
+ *
+ * @chroma_step is the distance in bytes from one chroma pixel value to the
+ * next.  This is 2 bytes for semiplanar (because chroma values are interleaved
+ * and each chroma value is one byte) and 1 for planar.
+ */
+
+struct android_ycbcr {
+    void *y;
+    void *cb;
+    void *cr;
+    size_t ystride;
+    size_t cstride;
+    size_t chroma_step;
+
+    /** reserved for future use, set to 0 by gralloc's (*lock_ycbcr)() */
+    uint32_t reserved[8];
+};
+
+/**
+ * Transformation definitions
+ *
+ * IMPORTANT NOTE:
+ * HAL_TRANSFORM_ROT_90 is applied CLOCKWISE and AFTER HAL_TRANSFORM_FLIP_{H|V}.
+ *
+ */
+
+enum {
+    /* flip source image horizontally (around the vertical axis) */
+    HAL_TRANSFORM_FLIP_H    = 0x01,
+    /* flip source image vertically (around the horizontal axis)*/
+    HAL_TRANSFORM_FLIP_V    = 0x02,
+    /* rotate source image 90 degrees clockwise */
+    HAL_TRANSFORM_ROT_90    = 0x04,
+    /* rotate source image 180 degrees */
+    HAL_TRANSFORM_ROT_180   = 0x03,
+    /* rotate source image 270 degrees clockwise */
+    HAL_TRANSFORM_ROT_270   = 0x07,
+    /* don't use. see system/window.h */
+    HAL_TRANSFORM_RESERVED  = 0x08,
+};
+
+/**
+ * Colorspace Definitions
+ * ======================
+ *
+ * Colorspace is the definition of how pixel values should be interpreted.
+ * It includes primaries (including white point) and the transfer
+ * characteristic function, which describes both gamma curve and numeric
+ * range (within the bit depth).
+ */
+
+enum {
+    /*
+     * Arbitrary colorspace with manually defined characteristics.
+     * Colorspace definition must be communicated separately.
+     *
+     * This is used when specifying primaries, transfer characteristics,
+     * etc. separately.
+     *
+     * A typical use case is in video encoding parameters (e.g. for H.264),
+     * where a colorspace can have separately defined primaries, transfer
+     * characteristics, etc.
+     */
+    HAL_COLORSPACE_ARBITRARY = 0x1,
+
+    /*
+     * YCbCr Colorspaces
+     * -----------------
+     *
+     * Primaries are given using (x,y) coordinates in the CIE 1931 definition
+     * of x and y specified by ISO 11664-1.
+     *
+     * Transfer characteristics are the opto-electronic transfer characteristic
+     * at the source as a function of linear optical intensity (luminance).
+     */
+
+    /*
+     * JPEG File Interchange Format (JFIF)
+     *
+     * Same model as BT.601-625, but all values (Y, Cb, Cr) range from 0 to 255
+     *
+     * Transfer characteristic curve:
+     *  E = 1.099 * L ^ 0.45 - 0.099, 1.00 >= L >= 0.018
+     *  E = 4.500 L, 0.018 > L >= 0
+     *      L - luminance of image 0 <= L <= 1 for conventional colorimetry
+     *      E - corresponding electrical signal
+     *
+     * Primaries:       x       y
+     *  green           0.290   0.600
+     *  blue            0.150   0.060
+     *  red             0.640   0.330
+     *  white (D65)     0.3127  0.3290
+     */
+    HAL_COLORSPACE_JFIF = 0x101,
+
+    /*
+     * ITU-R Recommendation 601 (BT.601) - 625-line
+     *
+     * Standard-definition television, 625 Lines (PAL)
+     *
+     * For 8-bit-depth formats:
+     * Luma (Y) samples should range from 16 to 235, inclusive
+     * Chroma (Cb, Cr) samples should range from 16 to 240, inclusive
+     *
+     * For 10-bit-depth formats:
+     * Luma (Y) samples should range from 64 to 940, inclusive
+     * Chroma (Cb, Cr) samples should range from 64 to 960, inclusive
+     *
+     * Transfer characteristic curve:
+     *  E = 1.099 * L ^ 0.45 - 0.099, 1.00 >= L >= 0.018
+     *  E = 4.500 L, 0.018 > L >= 0
+     *      L - luminance of image 0 <= L <= 1 for conventional colorimetry
+     *      E - corresponding electrical signal
+     *
+     * Primaries:       x       y
+     *  green           0.290   0.600
+     *  blue            0.150   0.060
+     *  red             0.640   0.330
+     *  white (D65)     0.3127  0.3290
+     */
+    HAL_COLORSPACE_BT601_625 = 0x102,
+
+    /*
+     * ITU-R Recommendation 601 (BT.601) - 525-line
+     *
+     * Standard-definition television, 525 Lines (NTSC)
+     *
+     * For 8-bit-depth formats:
+     * Luma (Y) samples should range from 16 to 235, inclusive
+     * Chroma (Cb, Cr) samples should range from 16 to 240, inclusive
+     *
+     * For 10-bit-depth formats:
+     * Luma (Y) samples should range from 64 to 940, inclusive
+     * Chroma (Cb, Cr) samples should range from 64 to 960, inclusive
+     *
+     * Transfer characteristic curve:
+     *  E = 1.099 * L ^ 0.45 - 0.099, 1.00 >= L >= 0.018
+     *  E = 4.500 L, 0.018 > L >= 0
+     *      L - luminance of image 0 <= L <= 1 for conventional colorimetry
+     *      E - corresponding electrical signal
+     *
+     * Primaries:       x       y
+     *  green           0.310   0.595
+     *  blue            0.155   0.070
+     *  red             0.630   0.340
+     *  white (D65)     0.3127  0.3290
+     */
+    HAL_COLORSPACE_BT601_525 = 0x103,
+
+    /*
+     * ITU-R Recommendation 709 (BT.709)
+     *
+     * High-definition television
+     *
+     * For 8-bit-depth formats:
+     * Luma (Y) samples should range from 16 to 235, inclusive
+     * Chroma (Cb, Cr) samples should range from 16 to 240, inclusive
+     *
+     * For 10-bit-depth formats:
+     * Luma (Y) samples should range from 64 to 940, inclusive
+     * Chroma (Cb, Cr) samples should range from 64 to 960, inclusive
+     *
+     * Primaries:       x       y
+     *  green           0.300   0.600
+     *  blue            0.150   0.060
+     *  red             0.640   0.330
+     *  white (D65)     0.3127  0.3290
+     */
+    HAL_COLORSPACE_BT709 = 0x104,
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SYSTEM_CORE_INCLUDE_ANDROID_GRAPHICS_H */
diff --git a/package/utils/adbd/src/include/system/sound_trigger.h b/package/utils/adbd/src/include/system/sound_trigger.h
new file mode 100644
index 0000000..0270baa
--- /dev/null
+++ b/package/utils/adbd/src/include/system/sound_trigger.h
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2014 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 ANDROID_SOUND_TRIGGER_H
+#define ANDROID_SOUND_TRIGGER_H
+
+#include <stdbool.h>
+
+#define SOUND_TRIGGER_MAX_STRING_LEN 64 /* max length of strings in properties or
+                                           descriptor structs */
+#define SOUND_TRIGGER_MAX_LOCALE_LEN 6  /* max length of locale string. e.g en_US */
+#define SOUND_TRIGGER_MAX_USERS 10      /* max number of concurrent users */
+#define SOUND_TRIGGER_MAX_PHRASES 10    /* max number of concurrent phrases */
+
+#define RECOGNITION_MODE_VOICE_TRIGGER 0x1       /* simple voice trigger */
+#define RECOGNITION_MODE_USER_IDENTIFICATION 0x2 /* trigger only if one user in model identified */
+#define RECOGNITION_MODE_USER_AUTHENTICATION 0x4 /* trigger only if one user in mode
+                                                    authenticated */
+
+#define RECOGNITION_STATUS_SUCCESS 0
+#define RECOGNITION_STATUS_ABORT 1
+#define RECOGNITION_STATUS_FAILURE 2
+
+
+typedef enum {
+    SOUND_MODEL_TYPE_UNKNOWN = -1,    /* use for unspecified sound model type */
+    SOUND_MODEL_TYPE_KEYPHRASE = 0    /* use for key phrase sound models */
+} sound_trigger_sound_model_type_t;
+
+
+typedef struct sound_trigger_uuid_s {
+    unsigned int   timeLow;
+    unsigned short timeMid;
+    unsigned short timeHiAndVersion;
+    unsigned short clockSeq;
+    unsigned char  node[6];
+} sound_trigger_uuid_t;
+
+/*
+ * sound trigger implementation descriptor read by the framework via get_properties().
+ * Used by SoundTrigger service to report to applications and manage concurrency and policy.
+ */
+struct sound_trigger_properties {
+    char                 implementor[SOUND_TRIGGER_MAX_STRING_LEN]; /* implementor name */
+    char                 description[SOUND_TRIGGER_MAX_STRING_LEN]; /* implementation description */
+    unsigned int         version;               /* implementation version */
+    sound_trigger_uuid_t uuid;                  /* unique implementation ID.
+                                                   Must change with version each version */
+    unsigned int         max_sound_models;      /* maximum number of concurrent sound models
+                                                   loaded */
+    unsigned int         max_key_phrases;       /* maximum number of key phrases */
+    unsigned int         max_users;             /* maximum number of concurrent users detected */
+    unsigned int         recognition_modes;     /* all supported modes.
+                                                   e.g RECOGNITION_MODE_VOICE_TRIGGER */
+    bool                 capture_transition;    /* supports seamless transition from detection
+                                                   to capture */
+    unsigned int         max_buffer_ms;         /* maximum buffering capacity in ms if
+                                                   capture_transition is true*/
+    bool                 concurrent_capture;    /* supports capture by other use cases while
+                                                   detection is active */
+    unsigned int         power_consumption_mw;  /* Rated power consumption when detection is active
+                                                   with TDB silence/sound/speech ratio */
+};
+
+typedef int sound_trigger_module_handle_t;
+
+struct sound_trigger_module_descriptor {
+    sound_trigger_module_handle_t   handle;
+    struct sound_trigger_properties properties;
+};
+
+typedef int sound_model_handle_t;
+
+/*
+ * Generic sound model descriptor. This struct is the header of a larger block passed to
+ * load_sound_model() and containing the binary data of the sound model.
+ * Proprietary representation of users in binary data must match information indicated
+ * by users field
+ */
+struct sound_trigger_sound_model {
+    sound_trigger_sound_model_type_t type;        /* model type. e.g. SOUND_MODEL_TYPE_KEYPHRASE */
+    unsigned int                     data_size;   /* size of opaque model data */
+    unsigned int                     data_offset; /* offset of opaque data start from head of struct
+                                                    (e.g sizeof struct sound_trigger_sound_model) */
+};
+
+/* key phrase descriptor */
+struct sound_trigger_phrase {
+    unsigned int recognition_mode;  /* recognition modes supported by this key phrase */
+    unsigned int num_users;         /* number of users in the key phrase */
+    char         locale[SOUND_TRIGGER_MAX_LOCALE_LEN]; /* locale - JAVA Locale style (e.g. en_US) */
+    char         text[SOUND_TRIGGER_MAX_STRING_LEN];   /* phrase text in UTF-8 format. */
+};
+
+/*
+ * Specialized sound model for key phrase detection.
+ * Proprietary representation of key phrases in binary data must match information indicated
+ * by phrases field
+ */
+struct sound_trigger_phrase_sound_model {
+    struct sound_trigger_sound_model common;
+    unsigned int                     num_phrases;   /* number of key phrases in model */
+    struct sound_trigger_phrase      phrases[SOUND_TRIGGER_MAX_PHRASES];
+};
+
+
+/*
+ * Generic recognition event sent via recognition callback
+ */
+struct sound_trigger_recognition_event {
+    int                              status;            /* recognition status e.g.
+                                                           RECOGNITION_STATUS_SUCCESS */
+    sound_trigger_sound_model_type_t type;              /* event type, same as sound model type.
+                                                           e.g. SOUND_MODEL_TYPE_KEYPHRASE */
+    sound_model_handle_t             model;             /* loaded sound model that triggered the
+                                                           event */
+    bool                             capture_available; /* it is possible to capture audio from this
+                                                           utterance buffered by the
+                                                           implementation */
+    int                              capture_session;   /* audio session ID. framework use */
+    int                              capture_delay_ms;  /* delay in ms between end of model
+                                                           detection and start of audio available
+                                                           for capture. A negative value is possible
+                                                           (e.g. if key phrase is also available for
+                                                           capture */
+    unsigned int                     data_size;         /* size of opaque event data */
+    unsigned int                     data_offset;       /* offset of opaque data start from start of
+                                                          this struct (e.g sizeof struct
+                                                          sound_trigger_phrase_recognition_event) */
+};
+
+/*
+ * Specialized recognition event for key phrase detection
+ */
+struct sound_trigger_phrase_recognition_extra {
+    unsigned int recognition_modes;
+    unsigned int num_users;
+    unsigned int confidence_levels[SOUND_TRIGGER_MAX_USERS];
+};
+
+struct sound_trigger_phrase_recognition_event {
+    struct sound_trigger_recognition_event common;
+    bool                                   key_phrase_in_capture; /* true if the key phrase is
+                                                                     present in audio data available
+                                                                     for capture after recognition
+                                                                     event is fired */
+    unsigned int                           num_phrases;
+    struct sound_trigger_phrase_recognition_extra phrase_extras[SOUND_TRIGGER_MAX_PHRASES];
+};
+
+
+#endif  // ANDROID_SOUND_TRIGGER_H
diff --git a/package/utils/adbd/src/include/system/thread_defs.h b/package/utils/adbd/src/include/system/thread_defs.h
new file mode 100644
index 0000000..377a48c
--- /dev/null
+++ b/package/utils/adbd/src/include/system/thread_defs.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2013 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 ANDROID_THREAD_DEFS_H
+#define ANDROID_THREAD_DEFS_H
+
+#include "graphics.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+enum {
+    /*
+     * ***********************************************
+     * ** Keep in sync with android.os.Process.java **
+     * ***********************************************
+     *
+     * This maps directly to the "nice" priorities we use in Android.
+     * A thread priority should be chosen inverse-proportionally to
+     * the amount of work the thread is expected to do. The more work
+     * a thread will do, the less favorable priority it should get so that
+     * it doesn't starve the system. Threads not behaving properly might
+     * be "punished" by the kernel.
+     * Use the levels below when appropriate. Intermediate values are
+     * acceptable, preferably use the {MORE|LESS}_FAVORABLE constants below.
+     */
+    ANDROID_PRIORITY_LOWEST         =  19,
+
+    /* use for background tasks */
+    ANDROID_PRIORITY_BACKGROUND     =  10,
+
+    /* most threads run at normal priority */
+    ANDROID_PRIORITY_NORMAL         =   0,
+
+    /* threads currently running a UI that the user is interacting with */
+    ANDROID_PRIORITY_FOREGROUND     =  -2,
+
+    /* the main UI thread has a slightly more favorable priority */
+    ANDROID_PRIORITY_DISPLAY        =  -4,
+
+    /* ui service treads might want to run at a urgent display (uncommon) */
+    ANDROID_PRIORITY_URGENT_DISPLAY =  HAL_PRIORITY_URGENT_DISPLAY,
+
+    /* all normal audio threads */
+    ANDROID_PRIORITY_AUDIO          = -16,
+
+    /* service audio threads (uncommon) */
+    ANDROID_PRIORITY_URGENT_AUDIO   = -19,
+
+    /* should never be used in practice. regular process might not
+     * be allowed to use this level */
+    ANDROID_PRIORITY_HIGHEST        = -20,
+
+    ANDROID_PRIORITY_DEFAULT        = ANDROID_PRIORITY_NORMAL,
+    ANDROID_PRIORITY_MORE_FAVORABLE = -1,
+    ANDROID_PRIORITY_LESS_FAVORABLE = +1,
+};
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* ANDROID_THREAD_DEFS_H */
diff --git a/package/utils/adbd/src/include/system/window.h b/package/utils/adbd/src/include/system/window.h
new file mode 100644
index 0000000..3779653
--- /dev/null
+++ b/package/utils/adbd/src/include/system/window.h
@@ -0,0 +1,864 @@
+/*
+ * Copyright (C) 2011 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 SYSTEM_CORE_INCLUDE_ANDROID_WINDOW_H
+#define SYSTEM_CORE_INCLUDE_ANDROID_WINDOW_H
+
+#include <cutils/native_handle.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdint.h>
+#include <string.h>
+#include <system/graphics.h>
+#include <unistd.h>
+
+#ifndef __UNUSED
+#define __UNUSED __attribute__((__unused__))
+#endif
+#ifndef __deprecated
+#define __deprecated __attribute__((__deprecated__))
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*****************************************************************************/
+
+#define ANDROID_NATIVE_MAKE_CONSTANT(a,b,c,d) \
+    (((unsigned)(a)<<24)|((unsigned)(b)<<16)|((unsigned)(c)<<8)|(unsigned)(d))
+
+#define ANDROID_NATIVE_WINDOW_MAGIC \
+    ANDROID_NATIVE_MAKE_CONSTANT('_','w','n','d')
+
+#define ANDROID_NATIVE_BUFFER_MAGIC \
+    ANDROID_NATIVE_MAKE_CONSTANT('_','b','f','r')
+
+// ---------------------------------------------------------------------------
+
+// This #define may be used to conditionally compile device-specific code to
+// support either the prior ANativeWindow interface, which did not pass libsync
+// fences around, or the new interface that does.  This #define is only present
+// when the ANativeWindow interface does include libsync support.
+#define ANDROID_NATIVE_WINDOW_HAS_SYNC 1
+
+// ---------------------------------------------------------------------------
+
+typedef const native_handle_t* buffer_handle_t;
+
+// ---------------------------------------------------------------------------
+
+typedef struct android_native_rect_t
+{
+    int32_t left;
+    int32_t top;
+    int32_t right;
+    int32_t bottom;
+} android_native_rect_t;
+
+// ---------------------------------------------------------------------------
+
+typedef struct android_native_base_t
+{
+    /* a magic value defined by the actual EGL native type */
+    int magic;
+
+    /* the sizeof() of the actual EGL native type */
+    int version;
+
+    void* reserved[4];
+
+    /* reference-counting interface */
+    void (*incRef)(struct android_native_base_t* base);
+    void (*decRef)(struct android_native_base_t* base);
+} android_native_base_t;
+
+typedef struct ANativeWindowBuffer
+{
+#ifdef __cplusplus
+    ANativeWindowBuffer() {
+        common.magic = ANDROID_NATIVE_BUFFER_MAGIC;
+        common.version = sizeof(ANativeWindowBuffer);
+        memset(common.reserved, 0, sizeof(common.reserved));
+    }
+
+    // Implement the methods that sp<ANativeWindowBuffer> expects so that it
+    // can be used to automatically refcount ANativeWindowBuffer's.
+    void incStrong(const void* /*id*/) const {
+        common.incRef(const_cast<android_native_base_t*>(&common));
+    }
+    void decStrong(const void* /*id*/) const {
+        common.decRef(const_cast<android_native_base_t*>(&common));
+    }
+#endif
+
+    struct android_native_base_t common;
+
+    int width;
+    int height;
+    int stride;
+    int format;
+    int usage;
+
+    void* reserved[2];
+
+    buffer_handle_t handle;
+
+    void* reserved_proc[8];
+} ANativeWindowBuffer_t;
+
+// Old typedef for backwards compatibility.
+typedef ANativeWindowBuffer_t android_native_buffer_t;
+
+// ---------------------------------------------------------------------------
+
+/* attributes queriable with query() */
+enum {
+    NATIVE_WINDOW_WIDTH     = 0,
+    NATIVE_WINDOW_HEIGHT    = 1,
+    NATIVE_WINDOW_FORMAT    = 2,
+
+    /* The minimum number of buffers that must remain un-dequeued after a buffer
+     * has been queued.  This value applies only if set_buffer_count was used to
+     * override the number of buffers and if a buffer has since been queued.
+     * Users of the set_buffer_count ANativeWindow method should query this
+     * value before calling set_buffer_count.  If it is necessary to have N
+     * buffers simultaneously dequeued as part of the steady-state operation,
+     * and this query returns M then N+M buffers should be requested via
+     * native_window_set_buffer_count.
+     *
+     * Note that this value does NOT apply until a single buffer has been
+     * queued.  In particular this means that it is possible to:
+     *
+     * 1. Query M = min undequeued buffers
+     * 2. Set the buffer count to N + M
+     * 3. Dequeue all N + M buffers
+     * 4. Cancel M buffers
+     * 5. Queue, dequeue, queue, dequeue, ad infinitum
+     */
+    NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS = 3,
+
+    /* Check whether queueBuffer operations on the ANativeWindow send the buffer
+     * to the window compositor.  The query sets the returned 'value' argument
+     * to 1 if the ANativeWindow DOES send queued buffers directly to the window
+     * compositor and 0 if the buffers do not go directly to the window
+     * compositor.
+     *
+     * This can be used to determine whether protected buffer content should be
+     * sent to the ANativeWindow.  Note, however, that a result of 1 does NOT
+     * indicate that queued buffers will be protected from applications or users
+     * capturing their contents.  If that behavior is desired then some other
+     * mechanism (e.g. the GRALLOC_USAGE_PROTECTED flag) should be used in
+     * conjunction with this query.
+     */
+    NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER = 4,
+
+    /* Get the concrete type of a ANativeWindow.  See below for the list of
+     * possible return values.
+     *
+     * This query should not be used outside the Android framework and will
+     * likely be removed in the near future.
+     */
+    NATIVE_WINDOW_CONCRETE_TYPE = 5,
+
+
+    /*
+     * Default width and height of ANativeWindow buffers, these are the
+     * dimensions of the window buffers irrespective of the
+     * NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS call and match the native window
+     * size unless overridden by NATIVE_WINDOW_SET_BUFFERS_USER_DIMENSIONS.
+     */
+    NATIVE_WINDOW_DEFAULT_WIDTH = 6,
+    NATIVE_WINDOW_DEFAULT_HEIGHT = 7,
+
+    /*
+     * transformation that will most-likely be applied to buffers. This is only
+     * a hint, the actual transformation applied might be different.
+     *
+     * INTENDED USE:
+     *
+     * The transform hint can be used by a producer, for instance the GLES
+     * driver, to pre-rotate the rendering such that the final transformation
+     * in the composer is identity. This can be very useful when used in
+     * conjunction with the h/w composer HAL, in situations where it
+     * cannot handle arbitrary rotations.
+     *
+     * 1. Before dequeuing a buffer, the GL driver (or any other ANW client)
+     *    queries the ANW for NATIVE_WINDOW_TRANSFORM_HINT.
+     *
+     * 2. The GL driver overrides the width and height of the ANW to
+     *    account for NATIVE_WINDOW_TRANSFORM_HINT. This is done by querying
+     *    NATIVE_WINDOW_DEFAULT_{WIDTH | HEIGHT}, swapping the dimensions
+     *    according to NATIVE_WINDOW_TRANSFORM_HINT and calling
+     *    native_window_set_buffers_dimensions().
+     *
+     * 3. The GL driver dequeues a buffer of the new pre-rotated size.
+     *
+     * 4. The GL driver renders to the buffer such that the image is
+     *    already transformed, that is applying NATIVE_WINDOW_TRANSFORM_HINT
+     *    to the rendering.
+     *
+     * 5. The GL driver calls native_window_set_transform to apply
+     *    inverse transformation to the buffer it just rendered.
+     *    In order to do this, the GL driver needs
+     *    to calculate the inverse of NATIVE_WINDOW_TRANSFORM_HINT, this is
+     *    done easily:
+     *
+     *        int hintTransform, inverseTransform;
+     *        query(..., NATIVE_WINDOW_TRANSFORM_HINT, &hintTransform);
+     *        inverseTransform = hintTransform;
+     *        if (hintTransform & HAL_TRANSFORM_ROT_90)
+     *            inverseTransform ^= HAL_TRANSFORM_ROT_180;
+     *
+     *
+     * 6. The GL driver queues the pre-transformed buffer.
+     *
+     * 7. The composer combines the buffer transform with the display
+     *    transform.  If the buffer transform happens to cancel out the
+     *    display transform then no rotation is needed.
+     *
+     */
+    NATIVE_WINDOW_TRANSFORM_HINT = 8,
+
+    /*
+     * Boolean that indicates whether the consumer is running more than
+     * one buffer behind the producer.
+     */
+    NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND = 9,
+
+    /*
+     * The consumer gralloc usage bits currently set by the consumer.
+     * The values are defined in hardware/libhardware/include/gralloc.h.
+     */
+    NATIVE_WINDOW_CONSUMER_USAGE_BITS = 10
+};
+
+/* Valid operations for the (*perform)() hook.
+ *
+ * Values marked as 'deprecated' are supported, but have been superceded by
+ * other functionality.
+ *
+ * Values marked as 'private' should be considered private to the framework.
+ * HAL implementation code with access to an ANativeWindow should not use these,
+ * as it may not interact properly with the framework's use of the
+ * ANativeWindow.
+ */
+enum {
+    NATIVE_WINDOW_SET_USAGE                 =  0,
+    NATIVE_WINDOW_CONNECT                   =  1,   /* deprecated */
+    NATIVE_WINDOW_DISCONNECT                =  2,   /* deprecated */
+    NATIVE_WINDOW_SET_CROP                  =  3,   /* private */
+    NATIVE_WINDOW_SET_BUFFER_COUNT          =  4,
+    NATIVE_WINDOW_SET_BUFFERS_GEOMETRY      =  5,   /* deprecated */
+    NATIVE_WINDOW_SET_BUFFERS_TRANSFORM     =  6,
+    NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP     =  7,
+    NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS    =  8,
+    NATIVE_WINDOW_SET_BUFFERS_FORMAT        =  9,
+    NATIVE_WINDOW_SET_SCALING_MODE          = 10,   /* private */
+    NATIVE_WINDOW_LOCK                      = 11,   /* private */
+    NATIVE_WINDOW_UNLOCK_AND_POST           = 12,   /* private */
+    NATIVE_WINDOW_API_CONNECT               = 13,   /* private */
+    NATIVE_WINDOW_API_DISCONNECT            = 14,   /* private */
+    NATIVE_WINDOW_SET_BUFFERS_USER_DIMENSIONS = 15, /* private */
+    NATIVE_WINDOW_SET_POST_TRANSFORM_CROP   = 16,   /* private */
+};
+
+/* parameter for NATIVE_WINDOW_[API_][DIS]CONNECT */
+enum {
+    /* Buffers will be queued by EGL via eglSwapBuffers after being filled using
+     * OpenGL ES.
+     */
+    NATIVE_WINDOW_API_EGL = 1,
+
+    /* Buffers will be queued after being filled using the CPU
+     */
+    NATIVE_WINDOW_API_CPU = 2,
+
+    /* Buffers will be queued by Stagefright after being filled by a video
+     * decoder.  The video decoder can either be a software or hardware decoder.
+     */
+    NATIVE_WINDOW_API_MEDIA = 3,
+
+    /* Buffers will be queued by the the camera HAL.
+     */
+    NATIVE_WINDOW_API_CAMERA = 4,
+};
+
+/* parameter for NATIVE_WINDOW_SET_BUFFERS_TRANSFORM */
+enum {
+    /* flip source image horizontally */
+    NATIVE_WINDOW_TRANSFORM_FLIP_H = HAL_TRANSFORM_FLIP_H ,
+    /* flip source image vertically */
+    NATIVE_WINDOW_TRANSFORM_FLIP_V = HAL_TRANSFORM_FLIP_V,
+    /* rotate source image 90 degrees clock-wise, and is applied after TRANSFORM_FLIP_{H|V} */
+    NATIVE_WINDOW_TRANSFORM_ROT_90 = HAL_TRANSFORM_ROT_90,
+    /* rotate source image 180 degrees */
+    NATIVE_WINDOW_TRANSFORM_ROT_180 = HAL_TRANSFORM_ROT_180,
+    /* rotate source image 270 degrees clock-wise */
+    NATIVE_WINDOW_TRANSFORM_ROT_270 = HAL_TRANSFORM_ROT_270,
+    /* transforms source by the inverse transform of the screen it is displayed onto. This
+     * transform is applied last */
+    NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY = 0x08
+};
+
+/* parameter for NATIVE_WINDOW_SET_SCALING_MODE */
+enum {
+    /* the window content is not updated (frozen) until a buffer of
+     * the window size is received (enqueued)
+     */
+    NATIVE_WINDOW_SCALING_MODE_FREEZE           = 0,
+    /* the buffer is scaled in both dimensions to match the window size */
+    NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW  = 1,
+    /* the buffer is scaled uniformly such that the smaller dimension
+     * of the buffer matches the window size (cropping in the process)
+     */
+    NATIVE_WINDOW_SCALING_MODE_SCALE_CROP       = 2,
+    /* the window is clipped to the size of the buffer's crop rectangle; pixels
+     * outside the crop rectangle are treated as if they are completely
+     * transparent.
+     */
+    NATIVE_WINDOW_SCALING_MODE_NO_SCALE_CROP    = 3,
+};
+
+/* values returned by the NATIVE_WINDOW_CONCRETE_TYPE query */
+enum {
+    NATIVE_WINDOW_FRAMEBUFFER               = 0, /* FramebufferNativeWindow */
+    NATIVE_WINDOW_SURFACE                   = 1, /* Surface */
+};
+
+/* parameter for NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP
+ *
+ * Special timestamp value to indicate that timestamps should be auto-generated
+ * by the native window when queueBuffer is called.  This is equal to INT64_MIN,
+ * defined directly to avoid problems with C99/C++ inclusion of stdint.h.
+ */
+static const int64_t NATIVE_WINDOW_TIMESTAMP_AUTO = (-9223372036854775807LL-1);
+
+struct ANativeWindow
+{
+#ifdef __cplusplus
+    ANativeWindow()
+        : flags(0), minSwapInterval(0), maxSwapInterval(0), xdpi(0), ydpi(0)
+    {
+        common.magic = ANDROID_NATIVE_WINDOW_MAGIC;
+        common.version = sizeof(ANativeWindow);
+        memset(common.reserved, 0, sizeof(common.reserved));
+    }
+
+    /* Implement the methods that sp<ANativeWindow> expects so that it
+       can be used to automatically refcount ANativeWindow's. */
+    void incStrong(const void* /*id*/) const {
+        common.incRef(const_cast<android_native_base_t*>(&common));
+    }
+    void decStrong(const void* /*id*/) const {
+        common.decRef(const_cast<android_native_base_t*>(&common));
+    }
+#endif
+
+    struct android_native_base_t common;
+
+    /* flags describing some attributes of this surface or its updater */
+    const uint32_t flags;
+
+    /* min swap interval supported by this updated */
+    const int   minSwapInterval;
+
+    /* max swap interval supported by this updated */
+    const int   maxSwapInterval;
+
+    /* horizontal and vertical resolution in DPI */
+    const float xdpi;
+    const float ydpi;
+
+    /* Some storage reserved for the OEM's driver. */
+    intptr_t    oem[4];
+
+    /*
+     * Set the swap interval for this surface.
+     *
+     * Returns 0 on success or -errno on error.
+     */
+    int     (*setSwapInterval)(struct ANativeWindow* window,
+                int interval);
+
+    /*
+     * Hook called by EGL to acquire a buffer. After this call, the buffer
+     * is not locked, so its content cannot be modified. This call may block if
+     * no buffers are available.
+     *
+     * The window holds a reference to the buffer between dequeueBuffer and
+     * either queueBuffer or cancelBuffer, so clients only need their own
+     * reference if they might use the buffer after queueing or canceling it.
+     * Holding a reference to a buffer after queueing or canceling it is only
+     * allowed if a specific buffer count has been set.
+     *
+     * Returns 0 on success or -errno on error.
+     *
+     * XXX: This function is deprecated.  It will continue to work for some
+     * time for binary compatibility, but the new dequeueBuffer function that
+     * outputs a fence file descriptor should be used in its place.
+     */
+    int     (*dequeueBuffer_DEPRECATED)(struct ANativeWindow* window,
+                struct ANativeWindowBuffer** buffer);
+
+    /*
+     * hook called by EGL to lock a buffer. This MUST be called before modifying
+     * the content of a buffer. The buffer must have been acquired with
+     * dequeueBuffer first.
+     *
+     * Returns 0 on success or -errno on error.
+     *
+     * XXX: This function is deprecated.  It will continue to work for some
+     * time for binary compatibility, but it is essentially a no-op, and calls
+     * to it should be removed.
+     */
+    int     (*lockBuffer_DEPRECATED)(struct ANativeWindow* window,
+                struct ANativeWindowBuffer* buffer);
+
+    /*
+     * Hook called by EGL when modifications to the render buffer are done.
+     * This unlocks and post the buffer.
+     *
+     * The window holds a reference to the buffer between dequeueBuffer and
+     * either queueBuffer or cancelBuffer, so clients only need their own
+     * reference if they might use the buffer after queueing or canceling it.
+     * Holding a reference to a buffer after queueing or canceling it is only
+     * allowed if a specific buffer count has been set.
+     *
+     * Buffers MUST be queued in the same order than they were dequeued.
+     *
+     * Returns 0 on success or -errno on error.
+     *
+     * XXX: This function is deprecated.  It will continue to work for some
+     * time for binary compatibility, but the new queueBuffer function that
+     * takes a fence file descriptor should be used in its place (pass a value
+     * of -1 for the fence file descriptor if there is no valid one to pass).
+     */
+    int     (*queueBuffer_DEPRECATED)(struct ANativeWindow* window,
+                struct ANativeWindowBuffer* buffer);
+
+    /*
+     * hook used to retrieve information about the native window.
+     *
+     * Returns 0 on success or -errno on error.
+     */
+    int     (*query)(const struct ANativeWindow* window,
+                int what, int* value);
+
+    /*
+     * hook used to perform various operations on the surface.
+     * (*perform)() is a generic mechanism to add functionality to
+     * ANativeWindow while keeping backward binary compatibility.
+     *
+     * DO NOT CALL THIS HOOK DIRECTLY.  Instead, use the helper functions
+     * defined below.
+     *
+     *  (*perform)() returns -ENOENT if the 'what' parameter is not supported
+     *  by the surface's implementation.
+     *
+     * The valid operations are:
+     *     NATIVE_WINDOW_SET_USAGE
+     *     NATIVE_WINDOW_CONNECT               (deprecated)
+     *     NATIVE_WINDOW_DISCONNECT            (deprecated)
+     *     NATIVE_WINDOW_SET_CROP              (private)
+     *     NATIVE_WINDOW_SET_BUFFER_COUNT
+     *     NATIVE_WINDOW_SET_BUFFERS_GEOMETRY  (deprecated)
+     *     NATIVE_WINDOW_SET_BUFFERS_TRANSFORM
+     *     NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP
+     *     NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS
+     *     NATIVE_WINDOW_SET_BUFFERS_FORMAT
+     *     NATIVE_WINDOW_SET_SCALING_MODE       (private)
+     *     NATIVE_WINDOW_LOCK                   (private)
+     *     NATIVE_WINDOW_UNLOCK_AND_POST        (private)
+     *     NATIVE_WINDOW_API_CONNECT            (private)
+     *     NATIVE_WINDOW_API_DISCONNECT         (private)
+     *     NATIVE_WINDOW_SET_BUFFERS_USER_DIMENSIONS (private)
+     *     NATIVE_WINDOW_SET_POST_TRANSFORM_CROP (private)
+     *
+     */
+
+    int     (*perform)(struct ANativeWindow* window,
+                int operation, ... );
+
+    /*
+     * Hook used to cancel a buffer that has been dequeued.
+     * No synchronization is performed between dequeue() and cancel(), so
+     * either external synchronization is needed, or these functions must be
+     * called from the same thread.
+     *
+     * The window holds a reference to the buffer between dequeueBuffer and
+     * either queueBuffer or cancelBuffer, so clients only need their own
+     * reference if they might use the buffer after queueing or canceling it.
+     * Holding a reference to a buffer after queueing or canceling it is only
+     * allowed if a specific buffer count has been set.
+     *
+     * XXX: This function is deprecated.  It will continue to work for some
+     * time for binary compatibility, but the new cancelBuffer function that
+     * takes a fence file descriptor should be used in its place (pass a value
+     * of -1 for the fence file descriptor if there is no valid one to pass).
+     */
+    int     (*cancelBuffer_DEPRECATED)(struct ANativeWindow* window,
+                struct ANativeWindowBuffer* buffer);
+
+    /*
+     * Hook called by EGL to acquire a buffer. This call may block if no
+     * buffers are available.
+     *
+     * The window holds a reference to the buffer between dequeueBuffer and
+     * either queueBuffer or cancelBuffer, so clients only need their own
+     * reference if they might use the buffer after queueing or canceling it.
+     * Holding a reference to a buffer after queueing or canceling it is only
+     * allowed if a specific buffer count has been set.
+     *
+     * The libsync fence file descriptor returned in the int pointed to by the
+     * fenceFd argument will refer to the fence that must signal before the
+     * dequeued buffer may be written to.  A value of -1 indicates that the
+     * caller may access the buffer immediately without waiting on a fence.  If
+     * a valid file descriptor is returned (i.e. any value except -1) then the
+     * caller is responsible for closing the file descriptor.
+     *
+     * Returns 0 on success or -errno on error.
+     */
+    int     (*dequeueBuffer)(struct ANativeWindow* window,
+                struct ANativeWindowBuffer** buffer, int* fenceFd);
+
+    /*
+     * Hook called by EGL when modifications to the render buffer are done.
+     * This unlocks and post the buffer.
+     *
+     * The window holds a reference to the buffer between dequeueBuffer and
+     * either queueBuffer or cancelBuffer, so clients only need their own
+     * reference if they might use the buffer after queueing or canceling it.
+     * Holding a reference to a buffer after queueing or canceling it is only
+     * allowed if a specific buffer count has been set.
+     *
+     * The fenceFd argument specifies a libsync fence file descriptor for a
+     * fence that must signal before the buffer can be accessed.  If the buffer
+     * can be accessed immediately then a value of -1 should be used.  The
+     * caller must not use the file descriptor after it is passed to
+     * queueBuffer, and the ANativeWindow implementation is responsible for
+     * closing it.
+     *
+     * Returns 0 on success or -errno on error.
+     */
+    int     (*queueBuffer)(struct ANativeWindow* window,
+                struct ANativeWindowBuffer* buffer, int fenceFd);
+
+    /*
+     * Hook used to cancel a buffer that has been dequeued.
+     * No synchronization is performed between dequeue() and cancel(), so
+     * either external synchronization is needed, or these functions must be
+     * called from the same thread.
+     *
+     * The window holds a reference to the buffer between dequeueBuffer and
+     * either queueBuffer or cancelBuffer, so clients only need their own
+     * reference if they might use the buffer after queueing or canceling it.
+     * Holding a reference to a buffer after queueing or canceling it is only
+     * allowed if a specific buffer count has been set.
+     *
+     * The fenceFd argument specifies a libsync fence file decsriptor for a
+     * fence that must signal before the buffer can be accessed.  If the buffer
+     * can be accessed immediately then a value of -1 should be used.
+     *
+     * Note that if the client has not waited on the fence that was returned
+     * from dequeueBuffer, that same fence should be passed to cancelBuffer to
+     * ensure that future uses of the buffer are preceded by a wait on that
+     * fence.  The caller must not use the file descriptor after it is passed
+     * to cancelBuffer, and the ANativeWindow implementation is responsible for
+     * closing it.
+     *
+     * Returns 0 on success or -errno on error.
+     */
+    int     (*cancelBuffer)(struct ANativeWindow* window,
+                struct ANativeWindowBuffer* buffer, int fenceFd);
+};
+
+ /* Backwards compatibility: use ANativeWindow (struct ANativeWindow in C).
+  * android_native_window_t is deprecated.
+  */
+typedef struct ANativeWindow ANativeWindow;
+typedef struct ANativeWindow android_native_window_t __deprecated;
+
+/*
+ *  native_window_set_usage(..., usage)
+ *  Sets the intended usage flags for the next buffers
+ *  acquired with (*lockBuffer)() and on.
+ *  By default (if this function is never called), a usage of
+ *      GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE
+ *  is assumed.
+ *  Calling this function will usually cause following buffers to be
+ *  reallocated.
+ */
+
+static inline int native_window_set_usage(
+        struct ANativeWindow* window, int usage)
+{
+    return window->perform(window, NATIVE_WINDOW_SET_USAGE, usage);
+}
+
+/* deprecated. Always returns 0. Don't call. */
+static inline int native_window_connect(
+        struct ANativeWindow* window __UNUSED, int api __UNUSED) __deprecated;
+
+static inline int native_window_connect(
+        struct ANativeWindow* window __UNUSED, int api __UNUSED) {
+    return 0;
+}
+
+/* deprecated. Always returns 0. Don't call. */
+static inline int native_window_disconnect(
+        struct ANativeWindow* window __UNUSED, int api __UNUSED) __deprecated;
+
+static inline int native_window_disconnect(
+        struct ANativeWindow* window __UNUSED, int api __UNUSED) {
+    return 0;
+}
+
+/*
+ * native_window_set_crop(..., crop)
+ * Sets which region of the next queued buffers needs to be considered.
+ * Depending on the scaling mode, a buffer's crop region is scaled and/or
+ * cropped to match the surface's size.  This function sets the crop in
+ * pre-transformed buffer pixel coordinates.
+ *
+ * The specified crop region applies to all buffers queued after it is called.
+ *
+ * If 'crop' is NULL, subsequently queued buffers won't be cropped.
+ *
+ * An error is returned if for instance the crop region is invalid, out of the
+ * buffer's bound or if the window is invalid.
+ */
+static inline int native_window_set_crop(
+        struct ANativeWindow* window,
+        android_native_rect_t const * crop)
+{
+    return window->perform(window, NATIVE_WINDOW_SET_CROP, crop);
+}
+
+/*
+ * native_window_set_post_transform_crop(..., crop)
+ * Sets which region of the next queued buffers needs to be considered.
+ * Depending on the scaling mode, a buffer's crop region is scaled and/or
+ * cropped to match the surface's size.  This function sets the crop in
+ * post-transformed pixel coordinates.
+ *
+ * The specified crop region applies to all buffers queued after it is called.
+ *
+ * If 'crop' is NULL, subsequently queued buffers won't be cropped.
+ *
+ * An error is returned if for instance the crop region is invalid, out of the
+ * buffer's bound or if the window is invalid.
+ */
+static inline int native_window_set_post_transform_crop(
+        struct ANativeWindow* window,
+        android_native_rect_t const * crop)
+{
+    return window->perform(window, NATIVE_WINDOW_SET_POST_TRANSFORM_CROP, crop);
+}
+
+/*
+ * native_window_set_active_rect(..., active_rect)
+ *
+ * This function is deprecated and will be removed soon.  For now it simply
+ * sets the post-transform crop for compatibility while multi-project commits
+ * get checked.
+ */
+static inline int native_window_set_active_rect(
+        struct ANativeWindow* window,
+        android_native_rect_t const * active_rect) __deprecated;
+
+static inline int native_window_set_active_rect(
+        struct ANativeWindow* window,
+        android_native_rect_t const * active_rect)
+{
+    return native_window_set_post_transform_crop(window, active_rect);
+}
+
+/*
+ * native_window_set_buffer_count(..., count)
+ * Sets the number of buffers associated with this native window.
+ */
+static inline int native_window_set_buffer_count(
+        struct ANativeWindow* window,
+        size_t bufferCount)
+{
+    return window->perform(window, NATIVE_WINDOW_SET_BUFFER_COUNT, bufferCount);
+}
+
+/*
+ * native_window_set_buffers_geometry(..., int w, int h, int format)
+ * All buffers dequeued after this call will have the dimensions and format
+ * specified.  A successful call to this function has the same effect as calling
+ * native_window_set_buffers_size and native_window_set_buffers_format.
+ *
+ * XXX: This function is deprecated.  The native_window_set_buffers_dimensions
+ * and native_window_set_buffers_format functions should be used instead.
+ */
+static inline int native_window_set_buffers_geometry(
+        struct ANativeWindow* window,
+        int w, int h, int format) __deprecated;
+
+static inline int native_window_set_buffers_geometry(
+        struct ANativeWindow* window,
+        int w, int h, int format)
+{
+    return window->perform(window, NATIVE_WINDOW_SET_BUFFERS_GEOMETRY,
+            w, h, format);
+}
+
+/*
+ * native_window_set_buffers_dimensions(..., int w, int h)
+ * All buffers dequeued after this call will have the dimensions specified.
+ * In particular, all buffers will have a fixed-size, independent from the
+ * native-window size. They will be scaled according to the scaling mode
+ * (see native_window_set_scaling_mode) upon window composition.
+ *
+ * If w and h are 0, the normal behavior is restored. That is, dequeued buffers
+ * following this call will be sized to match the window's size.
+ *
+ * Calling this function will reset the window crop to a NULL value, which
+ * disables cropping of the buffers.
+ */
+static inline int native_window_set_buffers_dimensions(
+        struct ANativeWindow* window,
+        int w, int h)
+{
+    return window->perform(window, NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS,
+            w, h);
+}
+
+/*
+ * native_window_set_buffers_user_dimensions(..., int w, int h)
+ *
+ * Sets the user buffer size for the window, which overrides the
+ * window's size.  All buffers dequeued after this call will have the
+ * dimensions specified unless overridden by
+ * native_window_set_buffers_dimensions.  All buffers will have a
+ * fixed-size, independent from the native-window size. They will be
+ * scaled according to the scaling mode (see
+ * native_window_set_scaling_mode) upon window composition.
+ *
+ * If w and h are 0, the normal behavior is restored. That is, the
+ * default buffer size will match the windows's size.
+ *
+ * Calling this function will reset the window crop to a NULL value, which
+ * disables cropping of the buffers.
+ */
+static inline int native_window_set_buffers_user_dimensions(
+        struct ANativeWindow* window,
+        int w, int h)
+{
+    return window->perform(window, NATIVE_WINDOW_SET_BUFFERS_USER_DIMENSIONS,
+            w, h);
+}
+
+/*
+ * native_window_set_buffers_format(..., int format)
+ * All buffers dequeued after this call will have the format specified.
+ *
+ * If the specified format is 0, the default buffer format will be used.
+ */
+static inline int native_window_set_buffers_format(
+        struct ANativeWindow* window,
+        int format)
+{
+    return window->perform(window, NATIVE_WINDOW_SET_BUFFERS_FORMAT, format);
+}
+
+/*
+ * native_window_set_buffers_transform(..., int transform)
+ * All buffers queued after this call will be displayed transformed according
+ * to the transform parameter specified.
+ */
+static inline int native_window_set_buffers_transform(
+        struct ANativeWindow* window,
+        int transform)
+{
+    return window->perform(window, NATIVE_WINDOW_SET_BUFFERS_TRANSFORM,
+            transform);
+}
+
+/*
+ * native_window_set_buffers_timestamp(..., int64_t timestamp)
+ * All buffers queued after this call will be associated with the timestamp
+ * parameter specified. If the timestamp is set to NATIVE_WINDOW_TIMESTAMP_AUTO
+ * (the default), timestamps will be generated automatically when queueBuffer is
+ * called. The timestamp is measured in nanoseconds, and is normally monotonically
+ * increasing. The timestamp should be unaffected by time-of-day adjustments,
+ * and for a camera should be strictly monotonic but for a media player may be
+ * reset when the position is set.
+ */
+static inline int native_window_set_buffers_timestamp(
+        struct ANativeWindow* window,
+        int64_t timestamp)
+{
+    return window->perform(window, NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP,
+            timestamp);
+}
+
+/*
+ * native_window_set_scaling_mode(..., int mode)
+ * All buffers queued after this call will be associated with the scaling mode
+ * specified.
+ */
+static inline int native_window_set_scaling_mode(
+        struct ANativeWindow* window,
+        int mode)
+{
+    return window->perform(window, NATIVE_WINDOW_SET_SCALING_MODE,
+            mode);
+}
+
+/*
+ * native_window_api_connect(..., int api)
+ * connects an API to this window. only one API can be connected at a time.
+ * Returns -EINVAL if for some reason the window cannot be connected, which
+ * can happen if it's connected to some other API.
+ */
+static inline int native_window_api_connect(
+        struct ANativeWindow* window, int api)
+{
+    return window->perform(window, NATIVE_WINDOW_API_CONNECT, api);
+}
+
+/*
+ * native_window_api_disconnect(..., int api)
+ * disconnect the API from this window.
+ * An error is returned if for instance the window wasn't connected in the
+ * first place.
+ */
+static inline int native_window_api_disconnect(
+        struct ANativeWindow* window, int api)
+{
+    return window->perform(window, NATIVE_WINDOW_API_DISCONNECT, api);
+}
+
+/*
+ * native_window_dequeue_buffer_and_wait(...)
+ * Dequeue a buffer and wait on the fence associated with that buffer.  The
+ * buffer may safely be accessed immediately upon this function returning.  An
+ * error is returned if either of the dequeue or the wait operations fail.
+ */
+static inline int native_window_dequeue_buffer_and_wait(ANativeWindow *anw,
+        struct ANativeWindowBuffer** anb) {
+    return anw->dequeueBuffer_DEPRECATED(anw, anb);
+}
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SYSTEM_CORE_INCLUDE_ANDROID_WINDOW_H */
diff --git a/package/utils/adbd/src/include/sysutils/FrameworkClient.h b/package/utils/adbd/src/include/sysutils/FrameworkClient.h
new file mode 100644
index 0000000..4a3f0de
--- /dev/null
+++ b/package/utils/adbd/src/include/sysutils/FrameworkClient.h
@@ -0,0 +1,21 @@
+#ifndef _FRAMEWORK_CLIENT_H
+#define _FRAMEWORK_CLIENT_H
+
+#include "List.h"
+
+#include <pthread.h>
+
+class FrameworkClient {
+    int             mSocket;
+    pthread_mutex_t mWriteMutex;
+
+public:
+    FrameworkClient(int sock);
+    virtual ~FrameworkClient() {}
+
+    int sendMsg(const char *msg);
+    int sendMsg(const char *msg, const char *data);
+};
+
+typedef android::sysutils::List<FrameworkClient *> FrameworkClientCollection;
+#endif
diff --git a/package/utils/adbd/src/include/sysutils/FrameworkCommand.h b/package/utils/adbd/src/include/sysutils/FrameworkCommand.h
new file mode 100644
index 0000000..3e6264b
--- /dev/null
+++ b/package/utils/adbd/src/include/sysutils/FrameworkCommand.h
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+#ifndef __FRAMEWORK_CMD_HANDLER_H
+#define __FRAMEWORK_CMD_HANDLER_H
+
+#include "List.h"
+
+class SocketClient;
+
+class FrameworkCommand { 
+private:
+    const char *mCommand;
+
+public:
+
+    FrameworkCommand(const char *cmd);
+    virtual ~FrameworkCommand() { }
+
+    virtual int runCommand(SocketClient *c, int argc, char **argv) = 0;
+
+    const char *getCommand() { return mCommand; }
+};
+
+typedef android::sysutils::List<FrameworkCommand *> FrameworkCommandCollection;
+#endif
diff --git a/package/utils/adbd/src/include/sysutils/FrameworkListener.h b/package/utils/adbd/src/include/sysutils/FrameworkListener.h
new file mode 100644
index 0000000..18049cd
--- /dev/null
+++ b/package/utils/adbd/src/include/sysutils/FrameworkListener.h
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+#ifndef _FRAMEWORKSOCKETLISTENER_H
+#define _FRAMEWORKSOCKETLISTENER_H
+
+#include "SocketListener.h"
+#include "FrameworkCommand.h"
+
+class SocketClient;
+
+class FrameworkListener : public SocketListener {
+public:
+    static const int CMD_ARGS_MAX = 26;
+
+    /* 1 out of errorRate will be dropped */
+    int errorRate;
+
+private:
+    int mCommandCount;
+    bool mWithSeq;
+    FrameworkCommandCollection *mCommands;
+
+public:
+    FrameworkListener(const char *socketName);
+    FrameworkListener(const char *socketName, bool withSeq);
+    FrameworkListener(int sock);
+    virtual ~FrameworkListener() {}
+
+protected:
+    void registerCmd(FrameworkCommand *cmd);
+    virtual bool onDataAvailable(SocketClient *c);
+
+private:
+    void dispatchCommand(SocketClient *c, char *data);
+    void init(const char *socketName, bool withSeq);
+};
+#endif
diff --git a/package/utils/adbd/src/include/sysutils/List.h b/package/utils/adbd/src/include/sysutils/List.h
new file mode 100644
index 0000000..31f7b37
--- /dev/null
+++ b/package/utils/adbd/src/include/sysutils/List.h
@@ -0,0 +1,334 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+//
+// Templated list class.  Normally we'd use STL, but we don't have that.
+// This class mimics STL's interfaces.
+//
+// Objects are copied into the list with the '=' operator or with copy-
+// construction, so if the compiler's auto-generated versions won't work for
+// you, define your own.
+//
+// The only class you want to use from here is "List".
+//
+#ifndef _SYSUTILS_LIST_H
+#define _SYSUTILS_LIST_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+namespace android {
+namespace sysutils {
+
+/*
+ * Doubly-linked list.  Instantiate with "List<MyClass> myList".
+ *
+ * Objects added to the list are copied using the assignment operator,
+ * so this must be defined.
+ */
+template<typename T> 
+class List 
+{
+protected:
+    /*
+     * One element in the list.
+     */
+    class _Node {
+    public:
+        explicit _Node(const T& val) : mVal(val) {}
+        ~_Node() {}
+        inline T& getRef() { return mVal; }
+        inline const T& getRef() const { return mVal; }
+        inline _Node* getPrev() const { return mpPrev; }
+        inline _Node* getNext() const { return mpNext; }
+        inline void setVal(const T& val) { mVal = val; }
+        inline void setPrev(_Node* ptr) { mpPrev = ptr; }
+        inline void setNext(_Node* ptr) { mpNext = ptr; }
+    private:
+        friend class List;
+        friend class _ListIterator;
+        T           mVal;
+        _Node*      mpPrev;
+        _Node*      mpNext;
+    };
+
+    /*
+     * Iterator for walking through the list.
+     */
+    
+    template <typename TYPE>
+    struct CONST_ITERATOR {
+        typedef _Node const * NodePtr;
+        typedef const TYPE Type;
+    };
+    
+    template <typename TYPE>
+    struct NON_CONST_ITERATOR {
+        typedef _Node* NodePtr;
+        typedef TYPE Type;
+    };
+    
+    template<
+        typename U,
+        template <class> class Constness
+    > 
+    class _ListIterator {
+        typedef _ListIterator<U, Constness>     _Iter;
+        typedef typename Constness<U>::NodePtr  _NodePtr;
+        typedef typename Constness<U>::Type     _Type;
+
+        explicit _ListIterator(_NodePtr ptr) : mpNode(ptr) {}
+
+    public:
+        _ListIterator() {}
+        _ListIterator(const _Iter& rhs) : mpNode(rhs.mpNode) {}
+        ~_ListIterator() {}
+        
+        // this will handle conversions from iterator to const_iterator
+        // (and also all convertible iterators)
+        // Here, in this implementation, the iterators can be converted
+        // if the nodes can be converted
+        template<typename V> explicit 
+        _ListIterator(const V& rhs) : mpNode(rhs.mpNode) {}
+        
+
+        /*
+         * Dereference operator.  Used to get at the juicy insides.
+         */
+        _Type& operator*() const { return mpNode->getRef(); }
+        _Type* operator->() const { return &(mpNode->getRef()); }
+
+        /*
+         * Iterator comparison.
+         */
+        inline bool operator==(const _Iter& right) const { 
+            return mpNode == right.mpNode; }
+        
+        inline bool operator!=(const _Iter& right) const { 
+            return mpNode != right.mpNode; }
+
+        /*
+         * handle comparisons between iterator and const_iterator
+         */
+        template<typename OTHER>
+        inline bool operator==(const OTHER& right) const { 
+            return mpNode == right.mpNode; }
+        
+        template<typename OTHER>
+        inline bool operator!=(const OTHER& right) const { 
+            return mpNode != right.mpNode; }
+
+        /*
+         * Incr/decr, used to move through the list.
+         */
+        inline _Iter& operator++() {     // pre-increment
+            mpNode = mpNode->getNext();
+            return *this;
+        }
+        const _Iter operator++(int) {    // post-increment
+            _Iter tmp(*this);
+            mpNode = mpNode->getNext();
+            return tmp;
+        }
+        inline _Iter& operator--() {     // pre-increment
+            mpNode = mpNode->getPrev();
+            return *this;
+        }
+        const _Iter operator--(int) {   // post-increment
+            _Iter tmp(*this);
+            mpNode = mpNode->getPrev();
+            return tmp;
+        }
+
+        inline _NodePtr getNode() const { return mpNode; }
+
+        _NodePtr mpNode;    /* should be private, but older gcc fails */
+    private:
+        friend class List;
+    };
+
+public:
+    List() {
+        prep();
+    }
+    List(const List<T>& src) {      // copy-constructor
+        prep();
+        insert(begin(), src.begin(), src.end());
+    }
+    virtual ~List() {
+        clear();
+        delete[] (unsigned char*) mpMiddle;
+    }
+
+    typedef _ListIterator<T, NON_CONST_ITERATOR> iterator;
+    typedef _ListIterator<T, CONST_ITERATOR> const_iterator;
+
+    List<T>& operator=(const List<T>& right);
+
+    /* returns true if the list is empty */
+    inline bool empty() const { return mpMiddle->getNext() == mpMiddle; }
+
+    /* return #of elements in list */
+    size_t size() const {
+        return size_t(distance(begin(), end()));
+    }
+
+    /*
+     * Return the first element or one past the last element.  The
+     * _Node* we're returning is converted to an "iterator" by a
+     * constructor in _ListIterator.
+     */
+    inline iterator begin() { 
+        return iterator(mpMiddle->getNext()); 
+    }
+    inline const_iterator begin() const { 
+        return const_iterator(const_cast<_Node const*>(mpMiddle->getNext())); 
+    }
+    inline iterator end() { 
+        return iterator(mpMiddle); 
+    }
+    inline const_iterator end() const { 
+        return const_iterator(const_cast<_Node const*>(mpMiddle)); 
+    }
+
+    /* add the object to the head or tail of the list */
+    void push_front(const T& val) { insert(begin(), val); }
+    void push_back(const T& val) { insert(end(), val); }
+
+    /* insert before the current node; returns iterator at new node */
+    iterator insert(iterator posn, const T& val) 
+    {
+        _Node* newNode = new _Node(val);        // alloc & copy-construct
+        newNode->setNext(posn.getNode());
+        newNode->setPrev(posn.getNode()->getPrev());
+        posn.getNode()->getPrev()->setNext(newNode);
+        posn.getNode()->setPrev(newNode);
+        return iterator(newNode);
+    }
+
+    /* insert a range of elements before the current node */
+    void insert(iterator posn, const_iterator first, const_iterator last) {
+        for ( ; first != last; ++first)
+            insert(posn, *first);
+    }
+
+    /* remove one entry; returns iterator at next node */
+    iterator erase(iterator posn) {
+        _Node* pNext = posn.getNode()->getNext();
+        _Node* pPrev = posn.getNode()->getPrev();
+        pPrev->setNext(pNext);
+        pNext->setPrev(pPrev);
+        delete posn.getNode();
+        return iterator(pNext);
+    }
+
+    /* remove a range of elements */
+    iterator erase(iterator first, iterator last) {
+        while (first != last)
+            erase(first++);     // don't erase than incr later!
+        return iterator(last);
+    }
+
+    /* remove all contents of the list */
+    void clear() {
+        _Node* pCurrent = mpMiddle->getNext();
+        _Node* pNext;
+
+        while (pCurrent != mpMiddle) {
+            pNext = pCurrent->getNext();
+            delete pCurrent;
+            pCurrent = pNext;
+        }
+        mpMiddle->setPrev(mpMiddle);
+        mpMiddle->setNext(mpMiddle);
+    }
+
+    /*
+     * Measure the distance between two iterators.  On exist, "first"
+     * will be equal to "last".  The iterators must refer to the same
+     * list.
+     *
+     * FIXME: This is actually a generic iterator function. It should be a 
+     * template function at the top-level with specializations for things like
+     * vector<>, which can just do pointer math). Here we limit it to
+     * _ListIterator of the same type but different constness.
+     */
+    template<
+        typename U,
+        template <class> class CL,
+        template <class> class CR
+    > 
+    ptrdiff_t distance(
+            _ListIterator<U, CL> first, _ListIterator<U, CR> last) const 
+    {
+        ptrdiff_t count = 0;
+        while (first != last) {
+            ++first;
+            ++count;
+        }
+        return count;
+    }
+
+private:
+    /*
+     * I want a _Node but don't need it to hold valid data.  More
+     * to the point, I don't want T's constructor to fire, since it
+     * might have side-effects or require arguments.  So, we do this
+     * slightly uncouth storage alloc.
+     */
+    void prep() {
+        mpMiddle = (_Node*) new unsigned char[sizeof(_Node)];
+        mpMiddle->setPrev(mpMiddle);
+        mpMiddle->setNext(mpMiddle);
+    }
+
+    /*
+     * This node plays the role of "pointer to head" and "pointer to tail".
+     * It sits in the middle of a circular list of nodes.  The iterator
+     * runs around the circle until it encounters this one.
+     */
+    _Node*      mpMiddle;
+};
+
+/*
+ * Assignment operator.
+ *
+ * The simplest way to do this would be to clear out the target list and
+ * fill it with the source.  However, we can speed things along by
+ * re-using existing elements.
+ */
+template<class T>
+List<T>& List<T>::operator=(const List<T>& right)
+{
+    if (this == &right)
+        return *this;       // self-assignment
+    iterator firstDst = begin();
+    iterator lastDst = end();
+    const_iterator firstSrc = right.begin();
+    const_iterator lastSrc = right.end();
+    while (firstSrc != lastSrc && firstDst != lastDst)
+        *firstDst++ = *firstSrc++;
+    if (firstSrc == lastSrc)        // ran out of elements in source?
+        erase(firstDst, lastDst);   // yes, erase any extras
+    else
+        insert(lastDst, firstSrc, lastSrc);     // copy remaining over
+    return *this;
+}
+
+}; // namespace sysutils
+}; // namespace android
+
+#endif // _SYSUTILS_LIST_H
diff --git a/package/utils/adbd/src/include/sysutils/NetlinkEvent.h b/package/utils/adbd/src/include/sysutils/NetlinkEvent.h
new file mode 100644
index 0000000..c345cdb
--- /dev/null
+++ b/package/utils/adbd/src/include/sysutils/NetlinkEvent.h
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+#ifndef _NETLINKEVENT_H
+#define _NETLINKEVENT_H
+
+#include <sysutils/NetlinkListener.h>
+
+#define NL_PARAMS_MAX 32
+
+class NetlinkEvent {
+    int  mSeq;
+    char *mPath;
+    int  mAction;
+    char *mSubsystem;
+    char *mParams[NL_PARAMS_MAX];
+
+public:
+    const static int NlActionUnknown;
+    const static int NlActionAdd;
+    const static int NlActionRemove;
+    const static int NlActionChange;
+    const static int NlActionLinkDown;
+    const static int NlActionLinkUp;
+    const static int NlActionAddressUpdated;
+    const static int NlActionAddressRemoved;
+    const static int NlActionRdnss;
+    const static int NlActionRouteUpdated;
+    const static int NlActionRouteRemoved;
+
+    NetlinkEvent();
+    virtual ~NetlinkEvent();
+
+    bool decode(char *buffer, int size, int format = NetlinkListener::NETLINK_FORMAT_ASCII);
+    const char *findParam(const char *paramName);
+
+    const char *getSubsystem() { return mSubsystem; }
+    int getAction() { return mAction; }
+
+    void dump();
+
+ protected:
+    bool parseBinaryNetlinkMessage(char *buffer, int size);
+    bool parseAsciiNetlinkMessage(char *buffer, int size);
+    bool parseIfInfoMessage(const struct nlmsghdr *nh);
+    bool parseIfAddrMessage(const struct nlmsghdr *nh);
+    bool parseUlogPacketMessage(const struct nlmsghdr *nh);
+    bool parseRtMessage(const struct nlmsghdr *nh);
+    bool parseNdUserOptMessage(const struct nlmsghdr *nh);
+};
+
+#endif
diff --git a/package/utils/adbd/src/include/sysutils/NetlinkListener.h b/package/utils/adbd/src/include/sysutils/NetlinkListener.h
new file mode 100644
index 0000000..6e52c3b
--- /dev/null
+++ b/package/utils/adbd/src/include/sysutils/NetlinkListener.h
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+#ifndef _NETLINKLISTENER_H
+#define _NETLINKLISTENER_H
+
+#include "SocketListener.h"
+
+class NetlinkEvent;
+
+class NetlinkListener : public SocketListener {
+    char mBuffer[64 * 1024] __attribute__((aligned(4)));
+    int mFormat;
+
+public:
+    static const int NETLINK_FORMAT_ASCII = 0;
+    static const int NETLINK_FORMAT_BINARY = 1;
+
+#if 1
+    /* temporary version until we can get Motorola to update their
+     * ril.so.  Their prebuilt ril.so is using this private class
+     * so changing the NetlinkListener() constructor breaks their ril.
+     */
+    NetlinkListener(int socket);
+    NetlinkListener(int socket, int format);
+#else
+    NetlinkListener(int socket, int format = NETLINK_FORMAT_ASCII);
+#endif
+    virtual ~NetlinkListener() {}
+
+protected:
+    virtual bool onDataAvailable(SocketClient *cli);
+    virtual void onEvent(NetlinkEvent *evt) = 0;
+};
+
+#endif
diff --git a/package/utils/adbd/src/include/sysutils/ServiceManager.h b/package/utils/adbd/src/include/sysutils/ServiceManager.h
new file mode 100644
index 0000000..c31dd8f
--- /dev/null
+++ b/package/utils/adbd/src/include/sysutils/ServiceManager.h
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ */
+
+#ifndef _SERVICE_MANAGER_H
+#define _SERVICE_MANAGER_H
+
+class ServiceManager {
+public:
+    ServiceManager();
+    virtual ~ServiceManager() {}
+
+    int start(const char *name);
+    int stop(const char *name);
+    bool isRunning(const char *name);
+};
+
+#endif
diff --git a/package/utils/adbd/src/include/sysutils/SocketClient.h b/package/utils/adbd/src/include/sysutils/SocketClient.h
new file mode 100644
index 0000000..1004f06
--- /dev/null
+++ b/package/utils/adbd/src/include/sysutils/SocketClient.h
@@ -0,0 +1,88 @@
+#ifndef _SOCKET_CLIENT_H
+#define _SOCKET_CLIENT_H
+
+#include "List.h"
+
+#include <pthread.h>
+#include <cutils/atomic.h>
+#include <sys/types.h>
+#include <sys/uio.h>
+
+class SocketClient {
+    int             mSocket;
+    bool            mSocketOwned;
+    pthread_mutex_t mWriteMutex;
+
+    // Peer process ID
+    pid_t mPid;
+
+    // Peer user ID
+    uid_t mUid;
+
+    // Peer group ID
+    gid_t mGid;
+
+    // Reference count (starts at 1)
+    pthread_mutex_t mRefCountMutex;
+    int mRefCount;
+
+    int mCmdNum;
+
+    bool mUseCmdNum;
+
+public:
+    SocketClient(int sock, bool owned);
+    SocketClient(int sock, bool owned, bool useCmdNum);
+    virtual ~SocketClient();
+
+    int getSocket() { return mSocket; }
+    pid_t getPid() const { return mPid; }
+    uid_t getUid() const { return mUid; }
+    gid_t getGid() const { return mGid; }
+    void setCmdNum(int cmdNum) {
+        android_atomic_release_store(cmdNum, &mCmdNum);
+    }
+    int getCmdNum() { return mCmdNum; }
+
+    // Send null-terminated C strings:
+    int sendMsg(int code, const char *msg, bool addErrno);
+    int sendMsg(int code, const char *msg, bool addErrno, bool useCmdNum);
+    int sendMsg(const char *msg);
+
+    // Provides a mechanism to send a response code to the client.
+    // Sends the code and a null character.
+    int sendCode(int code);
+
+    // Provides a mechanism to send binary data to client.
+    // Sends the code and a null character, followed by 4 bytes of
+    // big-endian length, and the data.
+    int sendBinaryMsg(int code, const void *data, int len);
+
+    // Sending binary data:
+    int sendData(const void *data, int len);
+    // iovec contents not preserved through call
+    int sendDatav(struct iovec *iov, int iovcnt);
+
+    // Optional reference counting.  Reference count starts at 1.  If
+    // it's decremented to 0, it deletes itself.
+    // SocketListener creates a SocketClient (at refcount 1) and calls
+    // decRef() when it's done with the client.
+    void incRef();
+    bool decRef(); // returns true at 0 (but note: SocketClient already deleted)
+
+    // return a new string in quotes with '\\' and '\"' escaped for "my arg"
+    // transmissions
+    static char *quoteArg(const char *arg);
+
+private:
+    void init(int socket, bool owned, bool useCmdNum);
+
+    // Sending binary data. The caller should make sure this is protected
+    // from multiple threads entering simultaneously.
+    // returns 0 if successful, -1 if there is a 0 byte write or if any
+    // other error occurred (use errno to get the error)
+    int sendDataLockedv(struct iovec *iov, int iovcnt);
+};
+
+typedef android::sysutils::List<SocketClient *> SocketClientCollection;
+#endif
diff --git a/package/utils/adbd/src/include/sysutils/SocketClientCommand.h b/package/utils/adbd/src/include/sysutils/SocketClientCommand.h
new file mode 100644
index 0000000..746bc25
--- /dev/null
+++ b/package/utils/adbd/src/include/sysutils/SocketClientCommand.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2012 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 _SOCKETCLIENTCOMMAND_H
+#define _SOCKETCLIENTCOMMAND_H
+
+#include <sysutils/SocketClient.h>
+
+class SocketClientCommand {
+public:
+    virtual ~SocketClientCommand() { }
+    virtual void runSocketCommand(SocketClient *client) = 0;
+};
+
+#endif
diff --git a/package/utils/adbd/src/include/sysutils/SocketListener.h b/package/utils/adbd/src/include/sysutils/SocketListener.h
new file mode 100644
index 0000000..bc93b86
--- /dev/null
+++ b/package/utils/adbd/src/include/sysutils/SocketListener.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2008-2014 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 _SOCKETLISTENER_H
+#define _SOCKETLISTENER_H
+
+#include <pthread.h>
+
+#include <sysutils/SocketClient.h>
+#include "SocketClientCommand.h"
+
+class SocketListener {
+    bool                    mListen;
+    const char              *mSocketName;
+    int                     mSock;
+    SocketClientCollection  *mClients;
+    pthread_mutex_t         mClientsLock;
+    int                     mCtrlPipe[2];
+    pthread_t               mThread;
+    bool                    mUseCmdNum;
+
+public:
+    SocketListener(const char *socketName, bool listen);
+    SocketListener(const char *socketName, bool listen, bool useCmdNum);
+    SocketListener(int socketFd, bool listen);
+
+    virtual ~SocketListener();
+    int startListener();
+    int startListener(int backlog);
+    int stopListener();
+
+    void sendBroadcast(int code, const char *msg, bool addErrno);
+
+    void runOnEachSocket(SocketClientCommand *command);
+
+    bool release(SocketClient *c) { return release(c, true); }
+
+protected:
+    virtual bool onDataAvailable(SocketClient *c) = 0;
+
+private:
+    bool release(SocketClient *c, bool wakeup);
+    static void *threadStart(void *obj);
+    void runListener();
+    void init(const char *socketName, int socketFd, bool listen, bool useCmdNum);
+};
+#endif
diff --git a/package/utils/adbd/src/include/usbhost/usbhost.h b/package/utils/adbd/src/include/usbhost/usbhost.h
new file mode 100644
index 0000000..d26e931
--- /dev/null
+++ b/package/utils/adbd/src/include/usbhost/usbhost.h
@@ -0,0 +1,239 @@
+/*
+ * Copyright (C) 2010 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 __USB_HOST_H
+#define __USB_HOST_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+
+#include <linux/version.h>
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 20)
+#include <linux/usb/ch9.h>
+#else
+#include <linux/usb_ch9.h>
+#endif
+
+struct usb_host_context;
+struct usb_endpoint_descriptor;
+
+struct usb_descriptor_iter {
+    unsigned char*  config;
+    unsigned char*  config_end;
+    unsigned char*  curr_desc;
+};
+
+struct usb_request
+{
+    struct usb_device *dev;
+    void* buffer;
+    int buffer_length;
+    int actual_length;
+    int max_packet_size;
+    void *private_data; /* struct usbdevfs_urb* */
+    int endpoint;
+    void *client_data;  /* free for use by client */
+};
+
+/* Callback for notification when new USB devices are attached.
+ * Return true to exit from usb_host_run.
+ */
+typedef int (* usb_device_added_cb)(const char *dev_name, void *client_data);
+
+/* Callback for notification when USB devices are removed.
+ * Return true to exit from usb_host_run.
+ */
+typedef int (* usb_device_removed_cb)(const char *dev_name, void *client_data);
+
+/* Callback indicating that initial device discovery is done.
+ * Return true to exit from usb_host_run.
+ */
+typedef int (* usb_discovery_done_cb)(void *client_data);
+
+/* Call this to initialize the USB host library. */
+struct usb_host_context *usb_host_init(void);
+
+/* Call this to cleanup the USB host library. */
+void usb_host_cleanup(struct usb_host_context *context);
+
+/* Call this to get the inotify file descriptor. */
+int usb_host_get_fd(struct usb_host_context *context);
+
+/* Call this to initialize the usb host context. */
+int usb_host_load(struct usb_host_context *context,
+                  usb_device_added_cb added_cb,
+                  usb_device_removed_cb removed_cb,
+                  usb_discovery_done_cb discovery_done_cb,
+                  void *client_data);
+
+/* Call this to read and handle occuring usb event. */
+int usb_host_read_event(struct usb_host_context *context);
+
+/* Call this to monitor the USB bus for new and removed devices.
+ * This is intended to be called from a dedicated thread,
+ * as it will not return until one of the callbacks returns true.
+ * added_cb will be called immediately for each existing USB device,
+ * and subsequently each time a new device is added.
+ * removed_cb is called when USB devices are removed from the bus.
+ * discovery_done_cb is called after the initial discovery of already
+ * connected devices is complete.
+ */
+void usb_host_run(struct usb_host_context *context,
+                  usb_device_added_cb added_cb,
+                  usb_device_removed_cb removed_cb,
+                  usb_discovery_done_cb discovery_done_cb,
+                  void *client_data);
+
+/* Creates a usb_device object for a USB device */
+struct usb_device *usb_device_open(const char *dev_name);
+
+/* Releases all resources associated with the USB device */
+void usb_device_close(struct usb_device *device);
+
+/* Creates a usb_device object for already open USB device */
+struct usb_device *usb_device_new(const char *dev_name, int fd);
+
+/* Returns the file descriptor for the usb_device */
+int usb_device_get_fd(struct usb_device *device);
+
+/* Returns the name for the USB device, which is the same as
+ * the dev_name passed to usb_device_open()
+ */
+const char* usb_device_get_name(struct usb_device *device);
+
+/* Returns a unique ID for the device.
+ *Currently this is generated from the dev_name path.
+ */
+int usb_device_get_unique_id(struct usb_device *device);
+
+/* Returns a unique ID for the device name.
+ * Currently this is generated from the device path.
+ */
+int usb_device_get_unique_id_from_name(const char* name);
+
+/* Returns the device name for the unique ID.
+ * Call free() to deallocate the returned string */
+char* usb_device_get_name_from_unique_id(int id);
+
+/* Returns the USB vendor ID from the device descriptor for the USB device */
+uint16_t usb_device_get_vendor_id(struct usb_device *device);
+
+/* Returns the USB product ID from the device descriptor for the USB device */
+uint16_t usb_device_get_product_id(struct usb_device *device);
+
+const struct usb_device_descriptor* usb_device_get_device_descriptor(struct usb_device *device);
+
+/* Returns a USB descriptor string for the given string ID.
+ * Used to implement usb_device_get_manufacturer_name,
+ * usb_device_get_product_name and usb_device_get_serial.
+ * Call free() to free the result when you are done with it.
+ */
+char* usb_device_get_string(struct usb_device *device, int id);
+
+/* Returns the manufacturer name for the USB device.
+ * Call free() to free the result when you are done with it.
+ */
+char* usb_device_get_manufacturer_name(struct usb_device *device);
+
+/* Returns the product name for the USB device.
+ * Call free() to free the result when you are done with it.
+ */
+char* usb_device_get_product_name(struct usb_device *device);
+
+/* Returns the USB serial number for the USB device.
+ * Call free() to free the result when you are done with it.
+ */
+char* usb_device_get_serial(struct usb_device *device);
+
+/* Returns true if we have write access to the USB device,
+ * and false if we only have access to the USB device configuration.
+ */
+int usb_device_is_writeable(struct usb_device *device);
+
+/* Initializes a usb_descriptor_iter, which can be used to iterate through all
+ * the USB descriptors for a USB device.
+ */
+void usb_descriptor_iter_init(struct usb_device *device, struct usb_descriptor_iter *iter);
+
+/* Returns the next USB descriptor for a device, or NULL if we have reached the
+ * end of the list.
+ */
+struct usb_descriptor_header *usb_descriptor_iter_next(struct usb_descriptor_iter *iter);
+
+/* Claims the specified interface of a USB device */
+int usb_device_claim_interface(struct usb_device *device, unsigned int interface);
+
+/* Releases the specified interface of a USB device */
+int usb_device_release_interface(struct usb_device *device, unsigned int interface);
+
+/* Requests the kernel to connect or disconnect its driver for the specified interface.
+ * This can be used to ask the kernel to disconnect its driver for a device
+ * so usb_device_claim_interface can claim it instead.
+ */
+int usb_device_connect_kernel_driver(struct usb_device *device,
+        unsigned int interface, int connect);
+
+/* Sets the current configuration for the device to the specified configuration */
+int usb_device_set_configuration(struct usb_device *device, int configuration);
+
+/* Sets the specified interface of a USB device */
+int usb_device_set_interface(struct usb_device *device, unsigned int interface,
+                            unsigned int alt_setting);
+
+/* Sends a control message to the specified device on endpoint zero */
+int usb_device_control_transfer(struct usb_device *device,
+                            int requestType,
+                            int request,
+                            int value,
+                            int index,
+                            void* buffer,
+                            int length,
+                            unsigned int timeout);
+
+/* Reads or writes on a bulk endpoint.
+ * Returns number of bytes transferred, or negative value for error.
+ */
+int usb_device_bulk_transfer(struct usb_device *device,
+                            int endpoint,
+                            void* buffer,
+                            int length,
+                            unsigned int timeout);
+
+/* Creates a new usb_request. */
+struct usb_request *usb_request_new(struct usb_device *dev,
+        const struct usb_endpoint_descriptor *ep_desc);
+
+/* Releases all resources associated with the request */
+void usb_request_free(struct usb_request *req);
+
+/* Submits a read or write request on the specified device */
+int usb_request_queue(struct usb_request *req);
+
+ /* Waits for the results of a previous usb_request_queue operation.
+  * Returns a usb_request, or NULL for error.
+  */
+struct usb_request *usb_request_wait(struct usb_device *dev);
+
+/* Cancels a pending usb_request_queue() operation. */
+int usb_request_cancel(struct usb_request *req);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __USB_HOST_H */
diff --git a/package/utils/adbd/src/include/utils/AndroidThreads.h b/package/utils/adbd/src/include/utils/AndroidThreads.h
new file mode 100644
index 0000000..4eee14d
--- /dev/null
+++ b/package/utils/adbd/src/include/utils/AndroidThreads.h
@@ -0,0 +1,128 @@
+/*
+ * 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 _LIBS_UTILS_ANDROID_THREADS_H
+#define _LIBS_UTILS_ANDROID_THREADS_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#if defined(HAVE_PTHREADS)
+# include <pthread.h>
+#endif
+
+#include <utils/ThreadDefs.h>
+
+// ---------------------------------------------------------------------------
+// C API
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Create and run a new thread.
+extern int androidCreateThread(android_thread_func_t, void *);
+
+// Create thread with lots of parameters
+extern int androidCreateThreadEtc(android_thread_func_t entryFunction,
+                                  void *userData,
+                                  const char* threadName,
+                                  int32_t threadPriority,
+                                  size_t threadStackSize,
+                                  android_thread_id_t *threadId);
+
+// Get some sort of unique identifier for the current thread.
+extern android_thread_id_t androidGetThreadId();
+
+// Low-level thread creation -- never creates threads that can
+// interact with the Java VM.
+extern int androidCreateRawThreadEtc(android_thread_func_t entryFunction,
+                                     void *userData,
+                                     const char* threadName,
+                                     int32_t threadPriority,
+                                     size_t threadStackSize,
+                                     android_thread_id_t *threadId);
+
+// set the same of the running thread
+extern void androidSetThreadName(const char* name);
+
+// Used by the Java Runtime to control how threads are created, so that
+// they can be proper and lovely Java threads.
+typedef int (*android_create_thread_fn)(android_thread_func_t entryFunction,
+                                        void *userData,
+                                        const char* threadName,
+                                        int32_t threadPriority,
+                                        size_t threadStackSize,
+                                        android_thread_id_t *threadId);
+
+extern void androidSetCreateThreadFunc(android_create_thread_fn func);
+
+// ------------------------------------------------------------------
+// Extra functions working with raw pids.
+
+// Get pid for the current thread.
+extern pid_t androidGetTid();
+
+#ifdef HAVE_ANDROID_OS
+// Change the priority AND scheduling group of a particular thread.  The priority
+// should be one of the ANDROID_PRIORITY constants.  Returns INVALID_OPERATION
+// if the priority set failed, else another value if just the group set failed;
+// in either case errno is set.  Thread ID zero means current thread.
+extern int androidSetThreadPriority(pid_t tid, int prio);
+
+// Get the current priority of a particular thread. Returns one of the
+// ANDROID_PRIORITY constants or a negative result in case of error.
+extern int androidGetThreadPriority(pid_t tid);
+#endif
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+// ----------------------------------------------------------------------------
+// C++ API
+#ifdef __cplusplus
+namespace android {
+// ----------------------------------------------------------------------------
+
+// Create and run a new thread.
+inline bool createThread(thread_func_t f, void *a) {
+    return androidCreateThread(f, a) ? true : false;
+}
+
+// Create thread with lots of parameters
+inline bool createThreadEtc(thread_func_t entryFunction,
+                            void *userData,
+                            const char* threadName = "android:unnamed_thread",
+                            int32_t threadPriority = PRIORITY_DEFAULT,
+                            size_t threadStackSize = 0,
+                            thread_id_t *threadId = 0)
+{
+    return androidCreateThreadEtc(entryFunction, userData, threadName,
+        threadPriority, threadStackSize, threadId) ? true : false;
+}
+
+// Get some sort of unique identifier for the current thread.
+inline thread_id_t getThreadId() {
+    return androidGetThreadId();
+}
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+#endif  // __cplusplus
+// ----------------------------------------------------------------------------
+
+#endif // _LIBS_UTILS_ANDROID_THREADS_H
diff --git a/package/utils/adbd/src/include/utils/Atomic.h b/package/utils/adbd/src/include/utils/Atomic.h
new file mode 100644
index 0000000..7eb476c
--- /dev/null
+++ b/package/utils/adbd/src/include/utils/Atomic.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2005 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 ANDROID_UTILS_ATOMIC_H
+#define ANDROID_UTILS_ATOMIC_H
+
+#include <cutils/atomic.h>
+
+#endif // ANDROID_UTILS_ATOMIC_H
diff --git a/package/utils/adbd/src/include/utils/BasicHashtable.h b/package/utils/adbd/src/include/utils/BasicHashtable.h
new file mode 100644
index 0000000..c235d62
--- /dev/null
+++ b/package/utils/adbd/src/include/utils/BasicHashtable.h
@@ -0,0 +1,402 @@
+/*
+ * Copyright (C) 2011 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 ANDROID_BASIC_HASHTABLE_H
+#define ANDROID_BASIC_HASHTABLE_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <utils/SharedBuffer.h>
+#include <utils/TypeHelpers.h>
+
+namespace android {
+
+/* Implementation type.  Nothing to see here. */
+class BasicHashtableImpl {
+protected:
+    struct Bucket {
+        // The collision flag indicates that the bucket is part of a collision chain
+        // such that at least two entries both hash to this bucket.  When true, we
+        // may need to seek further along the chain to find the entry.
+        static const uint32_t COLLISION = 0x80000000UL;
+
+        // The present flag indicates that the bucket contains an initialized entry value.
+        static const uint32_t PRESENT   = 0x40000000UL;
+
+        // Mask for 30 bits worth of the hash code that are stored within the bucket to
+        // speed up lookups and rehashing by eliminating the need to recalculate the
+        // hash code of the entry's key.
+        static const uint32_t HASH_MASK = 0x3fffffffUL;
+
+        // Combined value that stores the collision and present flags as well as
+        // a 30 bit hash code.
+        uint32_t cookie;
+
+        // Storage for the entry begins here.
+        char entry[0];
+    };
+
+    BasicHashtableImpl(size_t entrySize, bool hasTrivialDestructor,
+            size_t minimumInitialCapacity, float loadFactor);
+    BasicHashtableImpl(const BasicHashtableImpl& other);
+    virtual ~BasicHashtableImpl();
+
+    void dispose();
+
+    inline void edit() {
+        if (mBuckets && !SharedBuffer::bufferFromData(mBuckets)->onlyOwner()) {
+            clone();
+        }
+    }
+
+    void setTo(const BasicHashtableImpl& other);
+    void clear();
+
+    ssize_t next(ssize_t index) const;
+    ssize_t find(ssize_t index, hash_t hash, const void* __restrict__ key) const;
+    size_t add(hash_t hash, const void* __restrict__ entry);
+    void removeAt(size_t index);
+    void rehash(size_t minimumCapacity, float loadFactor);
+
+    const size_t mBucketSize; // number of bytes per bucket including the entry
+    const bool mHasTrivialDestructor; // true if the entry type does not require destruction
+    size_t mCapacity;         // number of buckets that can be filled before exceeding load factor
+    float mLoadFactor;        // load factor
+    size_t mSize;             // number of elements actually in the table
+    size_t mFilledBuckets;    // number of buckets for which collision or present is true
+    size_t mBucketCount;      // number of slots in the mBuckets array
+    void* mBuckets;           // array of buckets, as a SharedBuffer
+
+    inline const Bucket& bucketAt(const void* __restrict__ buckets, size_t index) const {
+        return *reinterpret_cast<const Bucket*>(
+                static_cast<const uint8_t*>(buckets) + index * mBucketSize);
+    }
+
+    inline Bucket& bucketAt(void* __restrict__ buckets, size_t index) const {
+        return *reinterpret_cast<Bucket*>(static_cast<uint8_t*>(buckets) + index * mBucketSize);
+    }
+
+    virtual bool compareBucketKey(const Bucket& bucket, const void* __restrict__ key) const = 0;
+    virtual void initializeBucketEntry(Bucket& bucket, const void* __restrict__ entry) const = 0;
+    virtual void destroyBucketEntry(Bucket& bucket) const = 0;
+
+private:
+    void clone();
+
+    // Allocates a bucket array as a SharedBuffer.
+    void* allocateBuckets(size_t count) const;
+
+    // Releases a bucket array's associated SharedBuffer.
+    void releaseBuckets(void* __restrict__ buckets, size_t count) const;
+
+    // Destroys the contents of buckets (invokes destroyBucketEntry for each
+    // populated bucket if needed).
+    void destroyBuckets(void* __restrict__ buckets, size_t count) const;
+
+    // Copies the content of buckets (copies the cookie and invokes copyBucketEntry
+    // for each populated bucket if needed).
+    void copyBuckets(const void* __restrict__ fromBuckets,
+            void* __restrict__ toBuckets, size_t count) const;
+
+    // Determines the appropriate size of a bucket array to store a certain minimum
+    // number of entries and returns its effective capacity.
+    static void determineCapacity(size_t minimumCapacity, float loadFactor,
+            size_t* __restrict__ outBucketCount, size_t* __restrict__ outCapacity);
+
+    // Trim a hash code to 30 bits to match what we store in the bucket's cookie.
+    inline static hash_t trimHash(hash_t hash) {
+        return (hash & Bucket::HASH_MASK) ^ (hash >> 30);
+    }
+
+    // Returns the index of the first bucket that is in the collision chain
+    // for the specified hash code, given the total number of buckets.
+    // (Primary hash)
+    inline static size_t chainStart(hash_t hash, size_t count) {
+        return hash % count;
+    }
+
+    // Returns the increment to add to a bucket index to seek to the next bucket
+    // in the collision chain for the specified hash code, given the total number of buckets.
+    // (Secondary hash)
+    inline static size_t chainIncrement(hash_t hash, size_t count) {
+        return ((hash >> 7) | (hash << 25)) % (count - 1) + 1;
+    }
+
+    // Returns the index of the next bucket that is in the collision chain
+    // that is defined by the specified increment, given the total number of buckets.
+    inline static size_t chainSeek(size_t index, size_t increment, size_t count) {
+        return (index + increment) % count;
+    }
+};
+
+/*
+ * A BasicHashtable stores entries that are indexed by hash code in place
+ * within an array.  The basic operations are finding entries by key,
+ * adding new entries and removing existing entries.
+ *
+ * This class provides a very limited set of operations with simple semantics.
+ * It is intended to be used as a building block to construct more complex
+ * and interesting data structures such as HashMap.  Think very hard before
+ * adding anything extra to BasicHashtable, it probably belongs at a
+ * higher level of abstraction.
+ *
+ * TKey: The key type.
+ * TEntry: The entry type which is what is actually stored in the array.
+ *
+ * TKey must support the following contract:
+ *     bool operator==(const TKey& other) const;  // return true if equal
+ *     bool operator!=(const TKey& other) const;  // return true if unequal
+ *
+ * TEntry must support the following contract:
+ *     const TKey& getKey() const;  // get the key from the entry
+ *
+ * This class supports storing entries with duplicate keys.  Of course, it can't
+ * tell them apart during removal so only the first entry will be removed.
+ * We do this because it means that operations like add() can't fail.
+ */
+template <typename TKey, typename TEntry>
+class BasicHashtable : private BasicHashtableImpl {
+public:
+    /* Creates a hashtable with the specified minimum initial capacity.
+     * The underlying array will be created when the first entry is added.
+     *
+     * minimumInitialCapacity: The minimum initial capacity for the hashtable.
+     *     Default is 0.
+     * loadFactor: The desired load factor for the hashtable, between 0 and 1.
+     *     Default is 0.75.
+     */
+    BasicHashtable(size_t minimumInitialCapacity = 0, float loadFactor = 0.75f);
+
+    /* Copies a hashtable.
+     * The underlying storage is shared copy-on-write.
+     */
+    BasicHashtable(const BasicHashtable& other);
+
+    /* Clears and destroys the hashtable.
+     */
+    virtual ~BasicHashtable();
+
+    /* Making this hashtable a copy of the other hashtable.
+     * The underlying storage is shared copy-on-write.
+     *
+     * other: The hashtable to copy.
+     */
+    inline BasicHashtable<TKey, TEntry>& operator =(const BasicHashtable<TKey, TEntry> & other) {
+        setTo(other);
+        return *this;
+    }
+
+    /* Returns the number of entries in the hashtable.
+     */
+    inline size_t size() const {
+        return mSize;
+    }
+
+    /* Returns the capacity of the hashtable, which is the number of elements that can
+     * added to the hashtable without requiring it to be grown.
+     */
+    inline size_t capacity() const {
+        return mCapacity;
+    }
+
+    /* Returns the number of buckets that the hashtable has, which is the size of its
+     * underlying array.
+     */
+    inline size_t bucketCount() const {
+        return mBucketCount;
+    }
+
+    /* Returns the load factor of the hashtable. */
+    inline float loadFactor() const {
+        return mLoadFactor;
+    };
+
+    /* Returns a const reference to the entry at the specified index.
+     *
+     * index:   The index of the entry to retrieve.  Must be a valid index within
+     *          the bounds of the hashtable.
+     */
+    inline const TEntry& entryAt(size_t index) const {
+        return entryFor(bucketAt(mBuckets, index));
+    }
+
+    /* Returns a non-const reference to the entry at the specified index.
+     *
+     * index: The index of the entry to edit.  Must be a valid index within
+     *        the bounds of the hashtable.
+     */
+    inline TEntry& editEntryAt(size_t index) {
+        edit();
+        return entryFor(bucketAt(mBuckets, index));
+    }
+
+    /* Clears the hashtable.
+     * All entries in the hashtable are destroyed immediately.
+     * If you need to do something special with the entries in the hashtable then iterate
+     * over them and do what you need before clearing the hashtable.
+     */
+    inline void clear() {
+        BasicHashtableImpl::clear();
+    }
+
+    /* Returns the index of the next entry in the hashtable given the index of a previous entry.
+     * If the given index is -1, then returns the index of the first entry in the hashtable,
+     * if there is one, or -1 otherwise.
+     * If the given index is not -1, then returns the index of the next entry in the hashtable,
+     * in strictly increasing order, or -1 if there are none left.
+     *
+     * index:   The index of the previous entry that was iterated, or -1 to begin
+     *          iteration at the beginning of the hashtable.
+     */
+    inline ssize_t next(ssize_t index) const {
+        return BasicHashtableImpl::next(index);
+    }
+
+    /* Finds the index of an entry with the specified key.
+     * If the given index is -1, then returns the index of the first matching entry,
+     * otherwise returns the index of the next matching entry.
+     * If the hashtable contains multiple entries with keys that match the requested
+     * key, then the sequence of entries returned is arbitrary.
+     * Returns -1 if no entry was found.
+     *
+     * index:   The index of the previous entry with the specified key, or -1 to
+     *          find the first matching entry.
+     * hash:    The hashcode of the key.
+     * key:     The key.
+     */
+    inline ssize_t find(ssize_t index, hash_t hash, const TKey& key) const {
+        return BasicHashtableImpl::find(index, hash, &key);
+    }
+
+    /* Adds the entry to the hashtable.
+     * Returns the index of the newly added entry.
+     * If an entry with the same key already exists, then a duplicate entry is added.
+     * If the entry will not fit, then the hashtable's capacity is increased and
+     * its contents are rehashed.  See rehash().
+     *
+     * hash:    The hashcode of the key.
+     * entry:   The entry to add.
+     */
+    inline size_t add(hash_t hash, const TEntry& entry) {
+        return BasicHashtableImpl::add(hash, &entry);
+    }
+
+    /* Removes the entry with the specified index from the hashtable.
+     * The entry is destroyed immediately.
+     * The index must be valid.
+     *
+     * The hashtable is not compacted after an item is removed, so it is legal
+     * to continue iterating over the hashtable using next() or find().
+     *
+     * index:   The index of the entry to remove.  Must be a valid index within the
+     *          bounds of the hashtable, and it must refer to an existing entry.
+     */
+    inline void removeAt(size_t index) {
+        BasicHashtableImpl::removeAt(index);
+    }
+
+    /* Rehashes the contents of the hashtable.
+     * Grows the hashtable to at least the specified minimum capacity or the
+     * current number of elements, whichever is larger.
+     *
+     * Rehashing causes all entries to be copied and the entry indices may change.
+     * Although the hash codes are cached by the hashtable, rehashing can be an
+     * expensive operation and should be avoided unless the hashtable's size
+     * needs to be changed.
+     *
+     * Rehashing is the only way to change the capacity or load factor of the
+     * hashtable once it has been created.  It can be used to compact the
+     * hashtable by choosing a minimum capacity that is smaller than the current
+     * capacity (such as 0).
+     *
+     * minimumCapacity: The desired minimum capacity after rehashing.
+     * loadFactor: The desired load factor after rehashing.
+     */
+    inline void rehash(size_t minimumCapacity, float loadFactor) {
+        BasicHashtableImpl::rehash(minimumCapacity, loadFactor);
+    }
+
+    /* Determines whether there is room to add another entry without rehashing.
+     * When this returns true, a subsequent add() operation is guaranteed to
+     * complete without performing a rehash.
+     */
+    inline bool hasMoreRoom() const {
+        return mCapacity > mFilledBuckets;
+    }
+
+protected:
+    static inline const TEntry& entryFor(const Bucket& bucket) {
+        return reinterpret_cast<const TEntry&>(bucket.entry);
+    }
+
+    static inline TEntry& entryFor(Bucket& bucket) {
+        return reinterpret_cast<TEntry&>(bucket.entry);
+    }
+
+    virtual bool compareBucketKey(const Bucket& bucket, const void* __restrict__ key) const;
+    virtual void initializeBucketEntry(Bucket& bucket, const void* __restrict__ entry) const;
+    virtual void destroyBucketEntry(Bucket& bucket) const;
+
+private:
+    // For dumping the raw contents of a hashtable during testing.
+    friend class BasicHashtableTest;
+    inline uint32_t cookieAt(size_t index) const {
+        return bucketAt(mBuckets, index).cookie;
+    }
+};
+
+template <typename TKey, typename TEntry>
+BasicHashtable<TKey, TEntry>::BasicHashtable(size_t minimumInitialCapacity, float loadFactor) :
+        BasicHashtableImpl(sizeof(TEntry), traits<TEntry>::has_trivial_dtor,
+                minimumInitialCapacity, loadFactor) {
+}
+
+template <typename TKey, typename TEntry>
+BasicHashtable<TKey, TEntry>::BasicHashtable(const BasicHashtable<TKey, TEntry>& other) :
+        BasicHashtableImpl(other) {
+}
+
+template <typename TKey, typename TEntry>
+BasicHashtable<TKey, TEntry>::~BasicHashtable() {
+    dispose();
+}
+
+template <typename TKey, typename TEntry>
+bool BasicHashtable<TKey, TEntry>::compareBucketKey(const Bucket& bucket,
+        const void* __restrict__ key) const {
+    return entryFor(bucket).getKey() == *static_cast<const TKey*>(key);
+}
+
+template <typename TKey, typename TEntry>
+void BasicHashtable<TKey, TEntry>::initializeBucketEntry(Bucket& bucket,
+        const void* __restrict__ entry) const {
+    if (!traits<TEntry>::has_trivial_copy) {
+        new (&entryFor(bucket)) TEntry(*(static_cast<const TEntry*>(entry)));
+    } else {
+        memcpy(&entryFor(bucket), entry, sizeof(TEntry));
+    }
+}
+
+template <typename TKey, typename TEntry>
+void BasicHashtable<TKey, TEntry>::destroyBucketEntry(Bucket& bucket) const {
+    if (!traits<TEntry>::has_trivial_dtor) {
+        entryFor(bucket).~TEntry();
+    }
+}
+
+}; // namespace android
+
+#endif // ANDROID_BASIC_HASHTABLE_H
diff --git a/package/utils/adbd/src/include/utils/BitSet.h b/package/utils/adbd/src/include/utils/BitSet.h
new file mode 100644
index 0000000..8c61293
--- /dev/null
+++ b/package/utils/adbd/src/include/utils/BitSet.h
@@ -0,0 +1,294 @@
+/*
+ * Copyright (C) 2010 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 UTILS_BITSET_H
+#define UTILS_BITSET_H
+
+#include <stdint.h>
+#include <utils/TypeHelpers.h>
+
+/*
+ * Contains some bit manipulation helpers.
+ */
+
+namespace android {
+
+// A simple set of 32 bits that can be individually marked or cleared.
+struct BitSet32 {
+    uint32_t value;
+
+    inline BitSet32() : value(0UL) { }
+    explicit inline BitSet32(uint32_t value) : value(value) { }
+
+    // Gets the value associated with a particular bit index.
+    static inline uint32_t valueForBit(uint32_t n) { return 0x80000000UL >> n; }
+
+    // Clears the bit set.
+    inline void clear() { clear(value); }
+
+    static inline void clear(uint32_t& value) { value = 0UL; }
+
+    // Returns the number of marked bits in the set.
+    inline uint32_t count() const { return count(value); }
+
+    static inline uint32_t count(uint32_t value) { return __builtin_popcountl(value); }
+
+    // Returns true if the bit set does not contain any marked bits.
+    inline bool isEmpty() const { return isEmpty(value); }
+
+    static inline bool isEmpty(uint32_t value) { return ! value; }
+
+    // Returns true if the bit set does not contain any unmarked bits.
+    inline bool isFull() const { return isFull(value); }
+
+    static inline bool isFull(uint32_t value) { return value == 0xffffffffUL; }
+
+    // Returns true if the specified bit is marked.
+    inline bool hasBit(uint32_t n) const { return hasBit(value, n); }
+
+    static inline bool hasBit(uint32_t value, uint32_t n) { return value & valueForBit(n); }
+
+    // Marks the specified bit.
+    inline void markBit(uint32_t n) { markBit(value, n); }
+
+    static inline void markBit (uint32_t& value, uint32_t n) { value |= valueForBit(n); }
+
+    // Clears the specified bit.
+    inline void clearBit(uint32_t n) { clearBit(value, n); }
+
+    static inline void clearBit(uint32_t& value, uint32_t n) { value &= ~ valueForBit(n); }
+
+    // Finds the first marked bit in the set.
+    // Result is undefined if all bits are unmarked.
+    inline uint32_t firstMarkedBit() const { return firstMarkedBit(value); }
+
+    static uint32_t firstMarkedBit(uint32_t value) { return clz_checked(value); }
+
+    // Finds the first unmarked bit in the set.
+    // Result is undefined if all bits are marked.
+    inline uint32_t firstUnmarkedBit() const { return firstUnmarkedBit(value); }
+
+    static inline uint32_t firstUnmarkedBit(uint32_t value) { return clz_checked(~ value); }
+
+    // Finds the last marked bit in the set.
+    // Result is undefined if all bits are unmarked.
+    inline uint32_t lastMarkedBit() const { return lastMarkedBit(value); }
+
+    static inline uint32_t lastMarkedBit(uint32_t value) { return 31 - ctz_checked(value); }
+
+    // Finds the first marked bit in the set and clears it.  Returns the bit index.
+    // Result is undefined if all bits are unmarked.
+    inline uint32_t clearFirstMarkedBit() { return clearFirstMarkedBit(value); }
+
+    static inline uint32_t clearFirstMarkedBit(uint32_t& value) {
+        uint32_t n = firstMarkedBit(value);
+        clearBit(value, n);
+        return n;
+    }
+
+    // Finds the first unmarked bit in the set and marks it.  Returns the bit index.
+    // Result is undefined if all bits are marked.
+    inline uint32_t markFirstUnmarkedBit() { return markFirstUnmarkedBit(value); }
+
+    static inline uint32_t markFirstUnmarkedBit(uint32_t& value) {
+        uint32_t n = firstUnmarkedBit(value);
+        markBit(value, n);
+        return n;
+    }
+
+    // Finds the last marked bit in the set and clears it.  Returns the bit index.
+    // Result is undefined if all bits are unmarked.
+    inline uint32_t clearLastMarkedBit() { return clearLastMarkedBit(value); }
+
+    static inline uint32_t clearLastMarkedBit(uint32_t& value) {
+        uint32_t n = lastMarkedBit(value);
+        clearBit(value, n);
+        return n;
+    }
+
+    // Gets the index of the specified bit in the set, which is the number of
+    // marked bits that appear before the specified bit.
+    inline uint32_t getIndexOfBit(uint32_t n) const {
+        return getIndexOfBit(value, n);
+    }
+
+    static inline uint32_t getIndexOfBit(uint32_t value, uint32_t n) {
+        return __builtin_popcountl(value & ~(0xffffffffUL >> n));
+    }
+
+    inline bool operator== (const BitSet32& other) const { return value == other.value; }
+    inline bool operator!= (const BitSet32& other) const { return value != other.value; }
+    inline BitSet32 operator& (const BitSet32& other) const {
+        return BitSet32(value & other.value);
+    }
+    inline BitSet32& operator&= (const BitSet32& other) {
+        value &= other.value;
+        return *this;
+    }
+    inline BitSet32 operator| (const BitSet32& other) const {
+        return BitSet32(value | other.value);
+    }
+    inline BitSet32& operator|= (const BitSet32& other) {
+        value |= other.value;
+        return *this;
+    }
+
+private:
+    // We use these helpers as the signature of __builtin_c{l,t}z has "unsigned int" for the
+    // input, which is only guaranteed to be 16b, not 32. The compiler should optimize this away.
+    static inline uint32_t clz_checked(uint32_t value) {
+        if (sizeof(unsigned int) == sizeof(uint32_t)) {
+            return __builtin_clz(value);
+        } else {
+            return __builtin_clzl(value);
+        }
+    }
+
+    static inline uint32_t ctz_checked(uint32_t value) {
+        if (sizeof(unsigned int) == sizeof(uint32_t)) {
+            return __builtin_ctz(value);
+        } else {
+            return __builtin_ctzl(value);
+        }
+    }
+};
+
+ANDROID_BASIC_TYPES_TRAITS(BitSet32)
+
+// A simple set of 64 bits that can be individually marked or cleared.
+struct BitSet64 {
+    uint64_t value;
+
+    inline BitSet64() : value(0ULL) { }
+    explicit inline BitSet64(uint64_t value) : value(value) { }
+
+    // Gets the value associated with a particular bit index.
+    static inline uint64_t valueForBit(uint32_t n) { return 0x8000000000000000ULL >> n; }
+
+    // Clears the bit set.
+    inline void clear() { clear(value); }
+
+    static inline void clear(uint64_t& value) { value = 0ULL; }
+
+    // Returns the number of marked bits in the set.
+    inline uint32_t count() const { return count(value); }
+
+    static inline uint32_t count(uint64_t value) { return __builtin_popcountll(value); }
+
+    // Returns true if the bit set does not contain any marked bits.
+    inline bool isEmpty() const { return isEmpty(value); }
+
+    static inline bool isEmpty(uint64_t value) { return ! value; }
+
+    // Returns true if the bit set does not contain any unmarked bits.
+    inline bool isFull() const { return isFull(value); }
+
+    static inline bool isFull(uint64_t value) { return value == 0xffffffffffffffffULL; }
+
+    // Returns true if the specified bit is marked.
+    inline bool hasBit(uint32_t n) const { return hasBit(value, n); }
+
+    static inline bool hasBit(uint64_t value, uint32_t n) { return value & valueForBit(n); }
+
+    // Marks the specified bit.
+    inline void markBit(uint32_t n) { markBit(value, n); }
+
+    static inline void markBit(uint64_t& value, uint32_t n) { value |= valueForBit(n); }
+
+    // Clears the specified bit.
+    inline void clearBit(uint32_t n) { clearBit(value, n); }
+
+    static inline void clearBit(uint64_t& value, uint32_t n) { value &= ~ valueForBit(n); }
+
+    // Finds the first marked bit in the set.
+    // Result is undefined if all bits are unmarked.
+    inline uint32_t firstMarkedBit() const { return firstMarkedBit(value); }
+
+    static inline uint32_t firstMarkedBit(uint64_t value) { return __builtin_clzll(value); }
+
+    // Finds the first unmarked bit in the set.
+    // Result is undefined if all bits are marked.
+    inline uint32_t firstUnmarkedBit() const { return firstUnmarkedBit(value); }
+
+    static inline uint32_t firstUnmarkedBit(uint64_t value) { return __builtin_clzll(~ value); }
+
+    // Finds the last marked bit in the set.
+    // Result is undefined if all bits are unmarked.
+    inline uint32_t lastMarkedBit() const { return lastMarkedBit(value); }
+
+    static inline uint32_t lastMarkedBit(uint64_t value) { return 63 - __builtin_ctzll(value); }
+
+    // Finds the first marked bit in the set and clears it.  Returns the bit index.
+    // Result is undefined if all bits are unmarked.
+    inline uint32_t clearFirstMarkedBit() { return clearFirstMarkedBit(value); }
+
+    static inline uint32_t clearFirstMarkedBit(uint64_t& value) {
+        uint64_t n = firstMarkedBit(value);
+        clearBit(value, n);
+        return n;
+    }
+
+    // Finds the first unmarked bit in the set and marks it.  Returns the bit index.
+    // Result is undefined if all bits are marked.
+    inline uint32_t markFirstUnmarkedBit() { return markFirstUnmarkedBit(value); }
+
+    static inline uint32_t markFirstUnmarkedBit(uint64_t& value) {
+        uint64_t n = firstUnmarkedBit(value);
+        markBit(value, n);
+        return n;
+    }
+
+    // Finds the last marked bit in the set and clears it.  Returns the bit index.
+    // Result is undefined if all bits are unmarked.
+    inline uint32_t clearLastMarkedBit() { return clearLastMarkedBit(value); }
+
+    static inline uint32_t clearLastMarkedBit(uint64_t& value) {
+        uint64_t n = lastMarkedBit(value);
+        clearBit(value, n);
+        return n;
+    }
+
+    // Gets the index of the specified bit in the set, which is the number of
+    // marked bits that appear before the specified bit.
+    inline uint32_t getIndexOfBit(uint32_t n) const { return getIndexOfBit(value, n); }
+
+    static inline uint32_t getIndexOfBit(uint64_t value, uint32_t n) {
+        return __builtin_popcountll(value & ~(0xffffffffffffffffULL >> n));
+    }
+
+    inline bool operator== (const BitSet64& other) const { return value == other.value; }
+    inline bool operator!= (const BitSet64& other) const { return value != other.value; }
+    inline BitSet64 operator& (const BitSet64& other) const {
+        return BitSet64(value & other.value);
+    }
+    inline BitSet64& operator&= (const BitSet64& other) {
+        value &= other.value;
+        return *this;
+    }
+    inline BitSet64 operator| (const BitSet64& other) const {
+        return BitSet64(value | other.value);
+    }
+    inline BitSet64& operator|= (const BitSet64& other) {
+        value |= other.value;
+        return *this;
+    }
+};
+
+ANDROID_BASIC_TYPES_TRAITS(BitSet64)
+
+} // namespace android
+
+#endif // UTILS_BITSET_H
diff --git a/package/utils/adbd/src/include/utils/BlobCache.h b/package/utils/adbd/src/include/utils/BlobCache.h
new file mode 100644
index 0000000..7d621e4
--- /dev/null
+++ b/package/utils/adbd/src/include/utils/BlobCache.h
@@ -0,0 +1,243 @@
+/*
+ ** Copyright 2011, 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 ANDROID_BLOB_CACHE_H
+#define ANDROID_BLOB_CACHE_H
+
+#include <stddef.h>
+
+#include <utils/Flattenable.h>
+#include <utils/RefBase.h>
+#include <utils/SortedVector.h>
+#include <utils/threads.h>
+
+namespace android {
+
+// A BlobCache is an in-memory cache for binary key/value pairs.  A BlobCache
+// does NOT provide any thread-safety guarantees.
+//
+// The cache contents can be serialized to an in-memory buffer or mmap'd file
+// and then reloaded in a subsequent execution of the program.  This
+// serialization is non-portable and the data should only be used by the device
+// that generated it.
+class BlobCache : public RefBase {
+
+public:
+
+    // Create an empty blob cache. The blob cache will cache key/value pairs
+    // with key and value sizes less than or equal to maxKeySize and
+    // maxValueSize, respectively. The total combined size of ALL cache entries
+    // (key sizes plus value sizes) will not exceed maxTotalSize.
+    BlobCache(size_t maxKeySize, size_t maxValueSize, size_t maxTotalSize);
+
+    // set inserts a new binary value into the cache and associates it with the
+    // given binary key.  If the key or value are too large for the cache then
+    // the cache remains unchanged.  This includes the case where a different
+    // value was previously associated with the given key - the old value will
+    // remain in the cache.  If the given key and value are small enough to be
+    // put in the cache (based on the maxKeySize, maxValueSize, and maxTotalSize
+    // values specified to the BlobCache constructor), then the key/value pair
+    // will be in the cache after set returns.  Note, however, that a subsequent
+    // call to set may evict old key/value pairs from the cache.
+    //
+    // Preconditions:
+    //   key != NULL
+    //   0 < keySize
+    //   value != NULL
+    //   0 < valueSize
+    void set(const void* key, size_t keySize, const void* value,
+            size_t valueSize);
+
+    // get retrieves from the cache the binary value associated with a given
+    // binary key.  If the key is present in the cache then the length of the
+    // binary value associated with that key is returned.  If the value argument
+    // is non-NULL and the size of the cached value is less than valueSize bytes
+    // then the cached value is copied into the buffer pointed to by the value
+    // argument.  If the key is not present in the cache then 0 is returned and
+    // the buffer pointed to by the value argument is not modified.
+    //
+    // Note that when calling get multiple times with the same key, the later
+    // calls may fail, returning 0, even if earlier calls succeeded.  The return
+    // value must be checked for each call.
+    //
+    // Preconditions:
+    //   key != NULL
+    //   0 < keySize
+    //   0 <= valueSize
+    size_t get(const void* key, size_t keySize, void* value, size_t valueSize);
+
+
+    // getFlattenedSize returns the number of bytes needed to store the entire
+    // serialized cache.
+    size_t getFlattenedSize() const;
+
+    // flatten serializes the current contents of the cache into the memory
+    // pointed to by 'buffer'.  The serialized cache contents can later be
+    // loaded into a BlobCache object using the unflatten method.  The contents
+    // of the BlobCache object will not be modified.
+    //
+    // Preconditions:
+    //   size >= this.getFlattenedSize()
+    status_t flatten(void* buffer, size_t size) const;
+
+    // unflatten replaces the contents of the cache with the serialized cache
+    // contents in the memory pointed to by 'buffer'.  The previous contents of
+    // the BlobCache will be evicted from the cache.  If an error occurs while
+    // unflattening the serialized cache contents then the BlobCache will be
+    // left in an empty state.
+    //
+    status_t unflatten(void const* buffer, size_t size);
+
+private:
+    // Copying is disallowed.
+    BlobCache(const BlobCache&);
+    void operator=(const BlobCache&);
+
+    // A random function helper to get around MinGW not having nrand48()
+    long int blob_random();
+
+    // clean evicts a randomly chosen set of entries from the cache such that
+    // the total size of all remaining entries is less than mMaxTotalSize/2.
+    void clean();
+
+    // isCleanable returns true if the cache is full enough for the clean method
+    // to have some effect, and false otherwise.
+    bool isCleanable() const;
+
+    // A Blob is an immutable sized unstructured data blob.
+    class Blob : public RefBase {
+    public:
+        Blob(const void* data, size_t size, bool copyData);
+        ~Blob();
+
+        bool operator<(const Blob& rhs) const;
+
+        const void* getData() const;
+        size_t getSize() const;
+
+    private:
+        // Copying is not allowed.
+        Blob(const Blob&);
+        void operator=(const Blob&);
+
+        // mData points to the buffer containing the blob data.
+        const void* mData;
+
+        // mSize is the size of the blob data in bytes.
+        size_t mSize;
+
+        // mOwnsData indicates whether or not this Blob object should free the
+        // memory pointed to by mData when the Blob gets destructed.
+        bool mOwnsData;
+    };
+
+    // A CacheEntry is a single key/value pair in the cache.
+    class CacheEntry {
+    public:
+        CacheEntry();
+        CacheEntry(const sp<Blob>& key, const sp<Blob>& value);
+        CacheEntry(const CacheEntry& ce);
+
+        bool operator<(const CacheEntry& rhs) const;
+        const CacheEntry& operator=(const CacheEntry&);
+
+        sp<Blob> getKey() const;
+        sp<Blob> getValue() const;
+
+        void setValue(const sp<Blob>& value);
+
+    private:
+
+        // mKey is the key that identifies the cache entry.
+        sp<Blob> mKey;
+
+        // mValue is the cached data associated with the key.
+        sp<Blob> mValue;
+    };
+
+    // A Header is the header for the entire BlobCache serialization format. No
+    // need to make this portable, so we simply write the struct out.
+    struct Header {
+        // mMagicNumber is the magic number that identifies the data as
+        // serialized BlobCache contents.  It must always contain 'Blb$'.
+        uint32_t mMagicNumber;
+
+        // mBlobCacheVersion is the serialization format version.
+        uint32_t mBlobCacheVersion;
+
+        // mDeviceVersion is the device-specific version of the cache.  This can
+        // be used to invalidate the cache.
+        uint32_t mDeviceVersion;
+
+        // mNumEntries is number of cache entries following the header in the
+        // data.
+        size_t mNumEntries;
+    };
+
+    // An EntryHeader is the header for a serialized cache entry.  No need to
+    // make this portable, so we simply write the struct out.  Each EntryHeader
+    // is followed imediately by the key data and then the value data.
+    //
+    // The beginning of each serialized EntryHeader is 4-byte aligned, so the
+    // number of bytes that a serialized cache entry will occupy is:
+    //
+    //   ((sizeof(EntryHeader) + keySize + valueSize) + 3) & ~3
+    //
+    struct EntryHeader {
+        // mKeySize is the size of the entry key in bytes.
+        size_t mKeySize;
+
+        // mValueSize is the size of the entry value in bytes.
+        size_t mValueSize;
+
+        // mData contains both the key and value data for the cache entry.  The
+        // key comes first followed immediately by the value.
+        uint8_t mData[];
+    };
+
+    // mMaxKeySize is the maximum key size that will be cached. Calls to
+    // BlobCache::set with a keySize parameter larger than mMaxKeySize will
+    // simply not add the key/value pair to the cache.
+    const size_t mMaxKeySize;
+
+    // mMaxValueSize is the maximum value size that will be cached. Calls to
+    // BlobCache::set with a valueSize parameter larger than mMaxValueSize will
+    // simply not add the key/value pair to the cache.
+    const size_t mMaxValueSize;
+
+    // mMaxTotalSize is the maximum size that all cache entries can occupy. This
+    // includes space for both keys and values. When a call to BlobCache::set
+    // would otherwise cause this limit to be exceeded, either the key/value
+    // pair passed to BlobCache::set will not be cached or other cache entries
+    // will be evicted from the cache to make room for the new entry.
+    const size_t mMaxTotalSize;
+
+    // mTotalSize is the total combined size of all keys and values currently in
+    // the cache.
+    size_t mTotalSize;
+
+    // mRandState is the pseudo-random number generator state. It is passed to
+    // nrand48 to generate random numbers when needed.
+    unsigned short mRandState[3];
+
+    // mCacheEntries stores all the cache entries that are resident in memory.
+    // Cache entries are added to it by the 'set' method.
+    SortedVector<CacheEntry> mCacheEntries;
+};
+
+}
+
+#endif // ANDROID_BLOB_CACHE_H
diff --git a/package/utils/adbd/src/include/utils/ByteOrder.h b/package/utils/adbd/src/include/utils/ByteOrder.h
new file mode 100644
index 0000000..baa3a83
--- /dev/null
+++ b/package/utils/adbd/src/include/utils/ByteOrder.h
@@ -0,0 +1,81 @@
+/*
+ * 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 _LIBS_UTILS_BYTE_ORDER_H
+#define _LIBS_UTILS_BYTE_ORDER_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#ifdef HAVE_WINSOCK
+#include <winsock2.h>
+#else
+#include <netinet/in.h>
+#endif
+
+/*
+ * These macros are like the hton/ntoh byte swapping macros,
+ * except they allow you to swap to and from the "device" byte
+ * order.  The device byte order is the endianness of the target
+ * device -- for the ARM CPUs we use today, this is little endian.
+ *
+ * Note that the byte swapping functions have not been optimized
+ * much; performance is currently not an issue for them since the
+ * intent is to allow us to avoid byte swapping on the device.
+ */
+
+static inline uint32_t android_swap_long(uint32_t v)
+{
+    return (v<<24) | ((v<<8)&0x00FF0000) | ((v>>8)&0x0000FF00) | (v>>24);
+}
+
+static inline uint16_t android_swap_short(uint16_t v)
+{
+    return (v<<8) | (v>>8);
+}
+
+#define DEVICE_BYTE_ORDER LITTLE_ENDIAN
+
+#if BYTE_ORDER == DEVICE_BYTE_ORDER
+
+#define	dtohl(x)	(x)
+#define	dtohs(x)	(x)
+#define	htodl(x)	(x)
+#define	htods(x)	(x)
+
+#else
+
+#define	dtohl(x)	(android_swap_long(x))
+#define	dtohs(x)	(android_swap_short(x))
+#define	htodl(x)	(android_swap_long(x))
+#define	htods(x)	(android_swap_short(x))
+
+#endif
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define fromlel(x) (x)
+#define fromles(x) (x)
+#define tolel(x) (x)
+#define toles(x) (x)
+#else
+#define fromlel(x) (android_swap_long(x))
+#define fromles(x) (android_swap_short(x))
+#define tolel(x) (android_swap_long(x))
+#define toles(x) (android_swap_short(x))
+#endif
+
+#endif // _LIBS_UTILS_BYTE_ORDER_H
diff --git a/package/utils/adbd/src/include/utils/CallStack.h b/package/utils/adbd/src/include/utils/CallStack.h
new file mode 100644
index 0000000..27e89f4
--- /dev/null
+++ b/package/utils/adbd/src/include/utils/CallStack.h
@@ -0,0 +1,72 @@
+/*
+ * 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 ANDROID_CALLSTACK_H
+#define ANDROID_CALLSTACK_H
+
+#include <android/log.h>
+#include <backtrace/backtrace_constants.h>
+#include <utils/String8.h>
+#include <utils/Vector.h>
+
+#include <stdint.h>
+#include <sys/types.h>
+
+namespace android {
+
+class Printer;
+
+// Collect/print the call stack (function, file, line) traces for a single thread.
+class CallStack {
+public:
+    // Create an empty call stack. No-op.
+    CallStack();
+    // Create a callstack with the current thread's stack trace.
+    // Immediately dump it to logcat using the given logtag.
+    CallStack(const char* logtag, int32_t ignoreDepth=1);
+    ~CallStack();
+
+    // Reset the stack frames (same as creating an empty call stack).
+    void clear() { mFrameLines.clear(); }
+
+    // Immediately collect the stack traces for the specified thread.
+    // The default is to dump the stack of the current call.
+    void update(int32_t ignoreDepth=1, pid_t tid=BACKTRACE_CURRENT_THREAD);
+
+    // Dump a stack trace to the log using the supplied logtag.
+    void log(const char* logtag,
+             android_LogPriority priority = ANDROID_LOG_DEBUG,
+             const char* prefix = 0) const;
+
+    // Dump a stack trace to the specified file descriptor.
+    void dump(int fd, int indent = 0, const char* prefix = 0) const;
+
+    // Return a string (possibly very long) containing the complete stack trace.
+    String8 toString(const char* prefix = 0) const;
+
+    // Dump a serialized representation of the stack trace to the specified printer.
+    void print(Printer& printer) const;
+
+    // Get the count of stack frames that are in this call stack.
+    size_t size() const { return mFrameLines.size(); }
+
+private:
+    Vector<String8> mFrameLines;
+};
+
+}; // namespace android
+
+#endif // ANDROID_CALLSTACK_H
diff --git a/package/utils/adbd/src/include/utils/Compat.h b/package/utils/adbd/src/include/utils/Compat.h
new file mode 100644
index 0000000..fb7748e
--- /dev/null
+++ b/package/utils/adbd/src/include/utils/Compat.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2010 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 __LIB_UTILS_COMPAT_H
+#define __LIB_UTILS_COMPAT_H
+
+#include <unistd.h>
+
+/* Compatibility definitions for non-Linux (i.e., BSD-based) hosts. */
+#ifndef HAVE_OFF64_T
+#if _FILE_OFFSET_BITS < 64
+#error "_FILE_OFFSET_BITS < 64; large files are not supported on this platform"
+#endif /* _FILE_OFFSET_BITS < 64 */
+
+typedef off_t off64_t;
+
+static inline off64_t lseek64(int fd, off64_t offset, int whence) {
+    return lseek(fd, offset, whence);
+}
+
+#ifdef HAVE_PREAD
+static inline ssize_t pread64(int fd, void* buf, size_t nbytes, off64_t offset) {
+    return pread(fd, buf, nbytes, offset);
+}
+#endif
+
+#endif /* !HAVE_OFF64_T */
+
+#if HAVE_PRINTF_ZD
+#  define ZD "%zd"
+#  define ZD_TYPE ssize_t
+#else
+#  define ZD "%ld"
+#  define ZD_TYPE long
+#endif
+
+/*
+ * TEMP_FAILURE_RETRY is defined by some, but not all, versions of
+ * <unistd.h>. (Alas, it is not as standard as we'd hoped!) So, if it's
+ * not already defined, then define it here.
+ */
+#ifndef TEMP_FAILURE_RETRY
+/* Used to retry syscalls that can return EINTR. */
+#define TEMP_FAILURE_RETRY(exp) ({         \
+    typeof (exp) _rc;                      \
+    do {                                   \
+        _rc = (exp);                       \
+    } while (_rc == -1 && errno == EINTR); \
+    _rc; })
+#endif
+
+#endif /* __LIB_UTILS_COMPAT_H */
diff --git a/package/utils/adbd/src/include/utils/Condition.h b/package/utils/adbd/src/include/utils/Condition.h
new file mode 100644
index 0000000..1c99d1a
--- /dev/null
+++ b/package/utils/adbd/src/include/utils/Condition.h
@@ -0,0 +1,158 @@
+/*
+ * 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 _LIBS_UTILS_CONDITION_H
+#define _LIBS_UTILS_CONDITION_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <time.h>
+
+#if defined(HAVE_PTHREADS)
+# include <pthread.h>
+#endif
+
+#include <utils/Errors.h>
+#include <utils/Mutex.h>
+#include <utils/Timers.h>
+
+// ---------------------------------------------------------------------------
+namespace android {
+// ---------------------------------------------------------------------------
+
+/*
+ * Condition variable class.  The implementation is system-dependent.
+ *
+ * Condition variables are paired up with mutexes.  Lock the mutex,
+ * call wait(), then either re-wait() if things aren't quite what you want,
+ * or unlock the mutex and continue.  All threads calling wait() must
+ * use the same mutex for a given Condition.
+ */
+class Condition {
+public:
+    enum {
+        PRIVATE = 0,
+        SHARED = 1
+    };
+
+    enum WakeUpType {
+        WAKE_UP_ONE = 0,
+        WAKE_UP_ALL = 1
+    };
+
+    Condition();
+    Condition(int type);
+    ~Condition();
+    // Wait on the condition variable.  Lock the mutex before calling.
+    status_t wait(Mutex& mutex);
+    // same with relative timeout
+    status_t waitRelative(Mutex& mutex, nsecs_t reltime);
+    // Signal the condition variable, allowing exactly one thread to continue.
+    void signal();
+    // Signal the condition variable, allowing one or all threads to continue.
+    void signal(WakeUpType type) {
+        if (type == WAKE_UP_ONE) {
+            signal();
+        } else {
+            broadcast();
+        }
+    }
+    // Signal the condition variable, allowing all threads to continue.
+    void broadcast();
+
+private:
+#if defined(HAVE_PTHREADS)
+    pthread_cond_t mCond;
+#else
+    void*   mState;
+#endif
+};
+
+// ---------------------------------------------------------------------------
+
+#if defined(HAVE_PTHREADS)
+
+inline Condition::Condition() {
+    pthread_cond_init(&mCond, NULL);
+}
+inline Condition::Condition(int type) {
+    if (type == SHARED) {
+        pthread_condattr_t attr;
+        pthread_condattr_init(&attr);
+        pthread_condattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
+        pthread_cond_init(&mCond, &attr);
+        pthread_condattr_destroy(&attr);
+    } else {
+        pthread_cond_init(&mCond, NULL);
+    }
+}
+inline Condition::~Condition() {
+    pthread_cond_destroy(&mCond);
+}
+inline status_t Condition::wait(Mutex& mutex) {
+    return -pthread_cond_wait(&mCond, &mutex.mMutex);
+}
+inline status_t Condition::waitRelative(Mutex& mutex, nsecs_t reltime) {
+#if defined(HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE)
+    struct timespec ts;
+    ts.tv_sec  = reltime/1000000000;
+    ts.tv_nsec = reltime%1000000000;
+    return -pthread_cond_timedwait_relative_np(&mCond, &mutex.mMutex, &ts);
+#else // HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE
+    struct timespec ts;
+#if defined(HAVE_POSIX_CLOCKS)
+    clock_gettime(CLOCK_REALTIME, &ts);
+#else // HAVE_POSIX_CLOCKS
+    // we don't support the clocks here.
+    struct timeval t;
+    gettimeofday(&t, NULL);
+    ts.tv_sec = t.tv_sec;
+    ts.tv_nsec= t.tv_usec*1000;
+#endif // HAVE_POSIX_CLOCKS
+    ts.tv_sec += reltime/1000000000;
+    ts.tv_nsec+= reltime%1000000000;
+    if (ts.tv_nsec >= 1000000000) {
+        ts.tv_nsec -= 1000000000;
+        ts.tv_sec  += 1;
+    }
+    return -pthread_cond_timedwait(&mCond, &mutex.mMutex, &ts);
+#endif // HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE
+}
+inline void Condition::signal() {
+    /*
+     * POSIX says pthread_cond_signal wakes up "one or more" waiting threads.
+     * However bionic follows the glibc guarantee which wakes up "exactly one"
+     * waiting thread.
+     *
+     * man 3 pthread_cond_signal
+     *   pthread_cond_signal restarts one of the threads that are waiting on
+     *   the condition variable cond. If no threads are waiting on cond,
+     *   nothing happens. If several threads are waiting on cond, exactly one
+     *   is restarted, but it is not specified which.
+     */
+    pthread_cond_signal(&mCond);
+}
+inline void Condition::broadcast() {
+    pthread_cond_broadcast(&mCond);
+}
+
+#endif // HAVE_PTHREADS
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+// ---------------------------------------------------------------------------
+
+#endif // _LIBS_UTILS_CONDITON_H
diff --git a/package/utils/adbd/src/include/utils/Debug.h b/package/utils/adbd/src/include/utils/Debug.h
new file mode 100644
index 0000000..08893bd
--- /dev/null
+++ b/package/utils/adbd/src/include/utils/Debug.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2005 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 ANDROID_UTILS_DEBUG_H
+#define ANDROID_UTILS_DEBUG_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+#ifdef __cplusplus
+template<bool> struct CompileTimeAssert;
+template<> struct CompileTimeAssert<true> {};
+#define COMPILE_TIME_ASSERT(_exp) \
+    template class CompileTimeAssert< (_exp) >;
+#endif
+#define COMPILE_TIME_ASSERT_FUNCTION_SCOPE(_exp) \
+    CompileTimeAssert<( _exp )>();
+
+// ---------------------------------------------------------------------------
+
+#ifdef __cplusplus
+template<bool C, typename LSH, typename RHS> struct CompileTimeIfElse;
+template<typename LHS, typename RHS> 
+struct CompileTimeIfElse<true,  LHS, RHS> { typedef LHS TYPE; };
+template<typename LHS, typename RHS> 
+struct CompileTimeIfElse<false, LHS, RHS> { typedef RHS TYPE; };
+#endif
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_UTILS_DEBUG_H
diff --git a/package/utils/adbd/src/include/utils/Endian.h b/package/utils/adbd/src/include/utils/Endian.h
new file mode 100644
index 0000000..19f2504
--- /dev/null
+++ b/package/utils/adbd/src/include/utils/Endian.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+//
+// Android endian-ness defines.
+//
+#ifndef _LIBS_UTILS_ENDIAN_H
+#define _LIBS_UTILS_ENDIAN_H
+
+#if defined(HAVE_ENDIAN_H)
+
+#include <endian.h>
+
+#else /*not HAVE_ENDIAN_H*/
+
+#define __BIG_ENDIAN 0x1000
+#define __LITTLE_ENDIAN 0x0001
+
+#if defined(HAVE_LITTLE_ENDIAN)
+# define __BYTE_ORDER __LITTLE_ENDIAN
+#else
+# define __BYTE_ORDER __BIG_ENDIAN
+#endif
+
+#endif /*not HAVE_ENDIAN_H*/
+
+#endif /*_LIBS_UTILS_ENDIAN_H*/
diff --git a/package/utils/adbd/src/include/utils/Errors.h b/package/utils/adbd/src/include/utils/Errors.h
new file mode 100644
index 0000000..46173db
--- /dev/null
+++ b/package/utils/adbd/src/include/utils/Errors.h
@@ -0,0 +1,88 @@
+/*
+ * 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 ANDROID_ERRORS_H
+#define ANDROID_ERRORS_H
+
+#include <sys/types.h>
+#include <errno.h>
+
+namespace android {
+
+// use this type to return error codes
+#ifdef HAVE_MS_C_RUNTIME
+typedef int         status_t;
+#else
+typedef int32_t     status_t;
+#endif
+
+/* the MS C runtime lacks a few error codes */
+
+/*
+ * Error codes. 
+ * All error codes are negative values.
+ */
+
+// Win32 #defines NO_ERROR as well.  It has the same value, so there's no
+// real conflict, though it's a bit awkward.
+#ifdef _WIN32
+# undef NO_ERROR
+#endif
+
+enum {
+    OK                = 0,    // Everything's swell.
+    NO_ERROR          = 0,    // No errors.
+
+    UNKNOWN_ERROR       = (-2147483647-1), // INT32_MIN value
+
+    NO_MEMORY           = -ENOMEM,
+    INVALID_OPERATION   = -ENOSYS,
+    BAD_VALUE           = -EINVAL,
+    BAD_TYPE            = (UNKNOWN_ERROR + 1),
+    NAME_NOT_FOUND      = -ENOENT,
+    PERMISSION_DENIED   = -EPERM,
+    NO_INIT             = -ENODEV,
+    ALREADY_EXISTS      = -EEXIST,
+    DEAD_OBJECT         = -EPIPE,
+    FAILED_TRANSACTION  = (UNKNOWN_ERROR + 2),
+    JPARKS_BROKE_IT     = -EPIPE,
+#if !defined(HAVE_MS_C_RUNTIME)
+    BAD_INDEX           = -EOVERFLOW,
+    NOT_ENOUGH_DATA     = -ENODATA,
+    WOULD_BLOCK         = -EWOULDBLOCK, 
+    TIMED_OUT           = -ETIMEDOUT,
+    UNKNOWN_TRANSACTION = -EBADMSG,
+#else    
+    BAD_INDEX           = -E2BIG,
+    NOT_ENOUGH_DATA     = (UNKNOWN_ERROR + 3),
+    WOULD_BLOCK         = (UNKNOWN_ERROR + 4),
+    TIMED_OUT           = (UNKNOWN_ERROR + 5),
+    UNKNOWN_TRANSACTION = (UNKNOWN_ERROR + 6),
+#endif    
+    FDS_NOT_ALLOWED     = (UNKNOWN_ERROR + 7),
+};
+
+// Restore define; enumeration is in "android" namespace, so the value defined
+// there won't work for Win32 code in a different namespace.
+#ifdef _WIN32
+# define NO_ERROR 0L
+#endif
+
+}; // namespace android
+    
+// ---------------------------------------------------------------------------
+    
+#endif // ANDROID_ERRORS_H
diff --git a/package/utils/adbd/src/include/utils/FileMap.h b/package/utils/adbd/src/include/utils/FileMap.h
new file mode 100644
index 0000000..dfe6d51
--- /dev/null
+++ b/package/utils/adbd/src/include/utils/FileMap.h
@@ -0,0 +1,136 @@
+/*
+ * 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.
+ */
+
+//
+// Encapsulate a shared file mapping.
+//
+#ifndef __LIBS_FILE_MAP_H
+#define __LIBS_FILE_MAP_H
+
+#include <sys/types.h>
+
+#include <utils/Compat.h>
+
+#ifdef HAVE_WIN32_FILEMAP
+#include <windows.h>
+#endif
+
+namespace android {
+
+/*
+ * This represents a memory-mapped file.  It might be the entire file or
+ * only part of it.  This requires a little bookkeeping because the mapping
+ * needs to be aligned on page boundaries, and in some cases we'd like to
+ * have multiple references to the mapped area without creating additional
+ * maps.
+ *
+ * This always uses MAP_SHARED.
+ *
+ * TODO: we should be able to create a new FileMap that is a subset of
+ * an existing FileMap and shares the underlying mapped pages.  Requires
+ * completing the refcounting stuff and possibly introducing the notion
+ * of a FileMap hierarchy.
+ */
+class FileMap {
+public:
+    FileMap(void);
+
+    /*
+     * Create a new mapping on an open file.
+     *
+     * Closing the file descriptor does not unmap the pages, so we don't
+     * claim ownership of the fd.
+     *
+     * Returns "false" on failure.
+     */
+    bool create(const char* origFileName, int fd,
+                off64_t offset, size_t length, bool readOnly);
+
+    /*
+     * Return the name of the file this map came from, if known.
+     */
+    const char* getFileName(void) const { return mFileName; }
+    
+    /*
+     * Get a pointer to the piece of the file we requested.
+     */
+    void* getDataPtr(void) const { return mDataPtr; }
+
+    /*
+     * Get the length we requested.
+     */
+    size_t getDataLength(void) const { return mDataLength; }
+
+    /*
+     * Get the data offset used to create this map.
+     */
+    off64_t getDataOffset(void) const { return mDataOffset; }
+
+    /*
+     * Get a "copy" of the object.
+     */
+    FileMap* acquire(void) { mRefCount++; return this; }
+
+    /*
+     * Call this when mapping is no longer needed.
+     */
+    void release(void) {
+        if (--mRefCount <= 0)
+            delete this;
+    }
+
+    /*
+     * This maps directly to madvise() values, but allows us to avoid
+     * including <sys/mman.h> everywhere.
+     */
+    enum MapAdvice {
+        NORMAL, RANDOM, SEQUENTIAL, WILLNEED, DONTNEED
+    };
+
+    /*
+     * Apply an madvise() call to the entire file.
+     *
+     * Returns 0 on success, -1 on failure.
+     */
+    int advise(MapAdvice advice);
+
+protected:
+    // don't delete objects; call release()
+    ~FileMap(void);
+
+private:
+    // these are not implemented
+    FileMap(const FileMap& src);
+    const FileMap& operator=(const FileMap& src);
+
+    int         mRefCount;      // reference count
+    char*       mFileName;      // original file name, if known
+    void*       mBasePtr;       // base of mmap area; page aligned
+    size_t      mBaseLength;    // length, measured from "mBasePtr"
+    off64_t     mDataOffset;    // offset used when map was created
+    void*       mDataPtr;       // start of requested data, offset from base
+    size_t      mDataLength;    // length, measured from "mDataPtr"
+#ifdef HAVE_WIN32_FILEMAP
+    HANDLE      mFileHandle;    // Win32 file handle
+    HANDLE      mFileMapping;   // Win32 file mapping handle
+#endif
+
+    static long mPageSize;
+};
+
+}; // namespace android
+
+#endif // __LIBS_FILE_MAP_H
diff --git a/package/utils/adbd/src/include/utils/Flattenable.h b/package/utils/adbd/src/include/utils/Flattenable.h
new file mode 100644
index 0000000..882a8b2
--- /dev/null
+++ b/package/utils/adbd/src/include/utils/Flattenable.h
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2010 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 ANDROID_UTILS_FLATTENABLE_H
+#define ANDROID_UTILS_FLATTENABLE_H
+
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <utils/Errors.h>
+#include <utils/Debug.h>
+
+namespace android {
+
+
+class FlattenableUtils {
+public:
+    template<int N>
+    static size_t align(size_t size) {
+        COMPILE_TIME_ASSERT_FUNCTION_SCOPE( !(N & (N-1)) );
+        return (size + (N-1)) & ~(N-1);
+    }
+
+    template<int N>
+    static size_t align(void const*& buffer) {
+        COMPILE_TIME_ASSERT_FUNCTION_SCOPE( !(N & (N-1)) );
+        intptr_t b = intptr_t(buffer);
+        buffer = (void*)((intptr_t(buffer) + (N-1)) & ~(N-1));
+        return size_t(intptr_t(buffer) - b);
+    }
+
+    template<int N>
+    static size_t align(void*& buffer) {
+        return align<N>( const_cast<void const*&>(buffer) );
+    }
+
+    static void advance(void*& buffer, size_t& size, size_t offset) {
+        buffer = reinterpret_cast<void*>( intptr_t(buffer) + offset );
+        size -= offset;
+    }
+
+    static void advance(void const*& buffer, size_t& size, size_t offset) {
+        buffer = reinterpret_cast<void const*>( intptr_t(buffer) + offset );
+        size -= offset;
+    }
+
+    // write a POD structure
+    template<typename T>
+    static void write(void*& buffer, size_t& size, const T& value) {
+        *static_cast<T*>(buffer) = value;
+        advance(buffer, size, sizeof(T));
+    }
+
+    // read a POD structure
+    template<typename T>
+    static void read(void const*& buffer, size_t& size, T& value) {
+        value = *static_cast<T const*>(buffer);
+        advance(buffer, size, sizeof(T));
+    }
+};
+
+
+/*
+ * The Flattenable protocol allows an object to serialize itself out
+ * to a byte-buffer and an array of file descriptors.
+ * Flattenable objects must implement this protocol.
+ */
+
+template <typename T>
+class Flattenable {
+public:
+    // size in bytes of the flattened object
+    inline size_t getFlattenedSize() const;
+
+    // number of file descriptors to flatten
+    inline size_t getFdCount() const;
+
+    // flattens the object into buffer.
+    // size should be at least of getFlattenedSize()
+    // file descriptors are written in the fds[] array but ownership is
+    // not transfered (ie: they must be dupped by the caller of
+    // flatten() if needed).
+    inline status_t flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const;
+
+    // unflattens the object from buffer.
+    // size should be equal to the value of getFlattenedSize() when the
+    // object was flattened.
+    // unflattened file descriptors are found in the fds[] array and
+    // don't need to be dupped(). ie: the caller of unflatten doesn't
+    // keep ownership. If a fd is not retained by unflatten() it must be
+    // explicitly closed.
+    inline status_t unflatten(void const*& buffer, size_t& size, int const*& fds, size_t& count);
+};
+
+template<typename T>
+inline size_t Flattenable<T>::getFlattenedSize() const {
+    return static_cast<T const*>(this)->T::getFlattenedSize();
+}
+template<typename T>
+inline size_t Flattenable<T>::getFdCount() const {
+    return static_cast<T const*>(this)->T::getFdCount();
+}
+template<typename T>
+inline status_t Flattenable<T>::flatten(
+        void*& buffer, size_t& size, int*& fds, size_t& count) const {
+    return static_cast<T const*>(this)->T::flatten(buffer, size, fds, count);
+}
+template<typename T>
+inline status_t Flattenable<T>::unflatten(
+        void const*& buffer, size_t& size, int const*& fds, size_t& count) {
+    return static_cast<T*>(this)->T::unflatten(buffer, size, fds, count);
+}
+
+/*
+ * LightFlattenable is a protocol allowing object to serialize themselves out
+ * to a byte-buffer. Because it doesn't handle file-descriptors,
+ * LightFlattenable is usually more size efficient than Flattenable.
+ * LightFlattenable objects must implement this protocol.
+ */
+template <typename T>
+class LightFlattenable {
+public:
+    // returns whether this object always flatten into the same size.
+    // for efficiency, this should always be inline.
+    inline bool isFixedSize() const;
+
+    // returns size in bytes of the flattened object. must be a constant.
+    inline size_t getFlattenedSize() const;
+
+    // flattens the object into buffer.
+    inline status_t flatten(void* buffer, size_t size) const;
+
+    // unflattens the object from buffer of given size.
+    inline status_t unflatten(void const* buffer, size_t size);
+};
+
+template <typename T>
+inline bool LightFlattenable<T>::isFixedSize() const {
+    return static_cast<T const*>(this)->T::isFixedSize();
+}
+template <typename T>
+inline size_t LightFlattenable<T>::getFlattenedSize() const {
+    return static_cast<T const*>(this)->T::getFlattenedSize();
+}
+template <typename T>
+inline status_t LightFlattenable<T>::flatten(void* buffer, size_t size) const {
+    return static_cast<T const*>(this)->T::flatten(buffer, size);
+}
+template <typename T>
+inline status_t LightFlattenable<T>::unflatten(void const* buffer, size_t size) {
+    return static_cast<T*>(this)->T::unflatten(buffer, size);
+}
+
+/*
+ * LightFlattenablePod is an implementation of the LightFlattenable protocol
+ * for POD (plain-old-data) objects.
+ * Simply derive from LightFlattenablePod<Foo> to make Foo flattenable; no
+ * need to implement any methods; obviously Foo must be a POD structure.
+ */
+template <typename T>
+class LightFlattenablePod : public LightFlattenable<T> {
+public:
+    inline bool isFixedSize() const {
+        return true;
+    }
+
+    inline size_t getFlattenedSize() const {
+        return sizeof(T);
+    }
+    inline status_t flatten(void* buffer, size_t size) const {
+        if (size < sizeof(T)) return NO_MEMORY;
+        *reinterpret_cast<T*>(buffer) = *static_cast<T const*>(this);
+        return NO_ERROR;
+    }
+    inline status_t unflatten(void const* buffer, size_t) {
+        *static_cast<T*>(this) = *reinterpret_cast<T const*>(buffer);
+        return NO_ERROR;
+    }
+};
+
+
+}; // namespace android
+
+
+#endif /* ANDROID_UTILS_FLATTENABLE_H */
diff --git a/package/utils/adbd/src/include/utils/Functor.h b/package/utils/adbd/src/include/utils/Functor.h
new file mode 100644
index 0000000..09ea614
--- /dev/null
+++ b/package/utils/adbd/src/include/utils/Functor.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2011 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 ANDROID_FUNCTOR_H
+#define ANDROID_FUNCTOR_H
+
+#include <utils/Errors.h>
+
+namespace  android {
+
+class Functor {
+public:
+    Functor() {}
+    virtual ~Functor() {}
+    virtual status_t operator ()(int /*what*/, void* /*data*/) { return NO_ERROR; }
+};
+
+}; // namespace android
+
+#endif // ANDROID_FUNCTOR_H
diff --git a/package/utils/adbd/src/include/utils/JenkinsHash.h b/package/utils/adbd/src/include/utils/JenkinsHash.h
new file mode 100644
index 0000000..7da5dbd
--- /dev/null
+++ b/package/utils/adbd/src/include/utils/JenkinsHash.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+/* Implementation of Jenkins one-at-a-time hash function. These choices are
+ * optimized for code size and portability, rather than raw speed. But speed
+ * should still be quite good.
+ **/
+
+#ifndef ANDROID_JENKINS_HASH_H
+#define ANDROID_JENKINS_HASH_H
+
+#include <utils/TypeHelpers.h>
+
+namespace android {
+
+/* The Jenkins hash of a sequence of 32 bit words A, B, C is:
+ * Whiten(Mix(Mix(Mix(0, A), B), C)) */
+
+inline uint32_t JenkinsHashMix(uint32_t hash, uint32_t data) {
+    hash += data;
+    hash += (hash << 10);
+    hash ^= (hash >> 6);
+    return hash;
+}
+
+hash_t JenkinsHashWhiten(uint32_t hash);
+
+/* Helpful utility functions for hashing data in 32 bit chunks */
+uint32_t JenkinsHashMixBytes(uint32_t hash, const uint8_t* bytes, size_t size);
+
+uint32_t JenkinsHashMixShorts(uint32_t hash, const uint16_t* shorts, size_t size);
+
+}
+
+#endif // ANDROID_JENKINS_HASH_H
diff --git a/package/utils/adbd/src/include/utils/KeyedVector.h b/package/utils/adbd/src/include/utils/KeyedVector.h
new file mode 100644
index 0000000..c4faae0
--- /dev/null
+++ b/package/utils/adbd/src/include/utils/KeyedVector.h
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2005 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 ANDROID_KEYED_VECTOR_H
+#define ANDROID_KEYED_VECTOR_H
+
+#include <assert.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <cutils/log.h>
+
+#include <utils/SortedVector.h>
+#include <utils/TypeHelpers.h>
+#include <utils/Errors.h>
+
+// ---------------------------------------------------------------------------
+
+namespace android {
+
+template <typename KEY, typename VALUE>
+class KeyedVector
+{
+public:
+    typedef KEY    key_type;
+    typedef VALUE  value_type;
+
+    inline                  KeyedVector();
+
+    /*
+     * empty the vector
+     */
+
+    inline  void            clear()                     { mVector.clear(); }
+
+    /*! 
+     * vector stats
+     */
+
+    //! returns number of items in the vector
+    inline  size_t          size() const                { return mVector.size(); }
+    //! returns whether or not the vector is empty
+    inline  bool            isEmpty() const             { return mVector.isEmpty(); }
+    //! returns how many items can be stored without reallocating the backing store
+    inline  size_t          capacity() const            { return mVector.capacity(); }
+    //! sets the capacity. capacity can never be reduced less than size()
+    inline ssize_t          setCapacity(size_t size)    { return mVector.setCapacity(size); }
+
+    // returns true if the arguments is known to be identical to this vector
+    inline bool isIdenticalTo(const KeyedVector& rhs) const;
+
+    /*! 
+     * accessors
+     */
+            const VALUE&    valueFor(const KEY& key) const;
+            const VALUE&    valueAt(size_t index) const;
+            const KEY&      keyAt(size_t index) const;
+            ssize_t         indexOfKey(const KEY& key) const;
+            const VALUE&    operator[] (size_t index) const;
+
+    /*!
+     * modifying the array
+     */
+
+            VALUE&          editValueFor(const KEY& key);
+            VALUE&          editValueAt(size_t index);
+
+            /*! 
+             * add/insert/replace items
+             */
+             
+            ssize_t         add(const KEY& key, const VALUE& item);
+            ssize_t         replaceValueFor(const KEY& key, const VALUE& item);
+            ssize_t         replaceValueAt(size_t index, const VALUE& item);
+
+    /*!
+     * remove items
+     */
+
+            ssize_t         removeItem(const KEY& key);
+            ssize_t         removeItemsAt(size_t index, size_t count = 1);
+            
+private:
+            SortedVector< key_value_pair_t<KEY, VALUE> >    mVector;
+};
+
+// KeyedVector<KEY, VALUE> can be trivially moved using memcpy() because its
+// underlying SortedVector can be trivially moved.
+template<typename KEY, typename VALUE> struct trait_trivial_move<KeyedVector<KEY, VALUE> > {
+    enum { value = trait_trivial_move<SortedVector< key_value_pair_t<KEY, VALUE> > >::value };
+};
+
+
+// ---------------------------------------------------------------------------
+
+/**
+ * Variation of KeyedVector that holds a default value to return when
+ * valueFor() is called with a key that doesn't exist.
+ */
+template <typename KEY, typename VALUE>
+class DefaultKeyedVector : public KeyedVector<KEY, VALUE>
+{
+public:
+    inline                  DefaultKeyedVector(const VALUE& defValue = VALUE());
+            const VALUE&    valueFor(const KEY& key) const;
+
+private:
+            VALUE                                           mDefault;
+};
+
+// ---------------------------------------------------------------------------
+
+template<typename KEY, typename VALUE> inline
+KeyedVector<KEY,VALUE>::KeyedVector()
+{
+}
+
+template<typename KEY, typename VALUE> inline
+bool KeyedVector<KEY,VALUE>::isIdenticalTo(const KeyedVector<KEY,VALUE>& rhs) const {
+    return mVector.array() == rhs.mVector.array();
+}
+
+template<typename KEY, typename VALUE> inline
+ssize_t KeyedVector<KEY,VALUE>::indexOfKey(const KEY& key) const {
+    return mVector.indexOf( key_value_pair_t<KEY,VALUE>(key) );
+}
+
+template<typename KEY, typename VALUE> inline
+const VALUE& KeyedVector<KEY,VALUE>::valueFor(const KEY& key) const {
+    ssize_t i = this->indexOfKey(key);
+    LOG_ALWAYS_FATAL_IF(i<0, "%s: key not found", __PRETTY_FUNCTION__);
+    return mVector.itemAt(i).value;
+}
+
+template<typename KEY, typename VALUE> inline
+const VALUE& KeyedVector<KEY,VALUE>::valueAt(size_t index) const {
+    return mVector.itemAt(index).value;
+}
+
+template<typename KEY, typename VALUE> inline
+const VALUE& KeyedVector<KEY,VALUE>::operator[] (size_t index) const {
+    return valueAt(index);
+}
+
+template<typename KEY, typename VALUE> inline
+const KEY& KeyedVector<KEY,VALUE>::keyAt(size_t index) const {
+    return mVector.itemAt(index).key;
+}
+
+template<typename KEY, typename VALUE> inline
+VALUE& KeyedVector<KEY,VALUE>::editValueFor(const KEY& key) {
+    ssize_t i = this->indexOfKey(key);
+    LOG_ALWAYS_FATAL_IF(i<0, "%s: key not found", __PRETTY_FUNCTION__);
+    return mVector.editItemAt(i).value;
+}
+
+template<typename KEY, typename VALUE> inline
+VALUE& KeyedVector<KEY,VALUE>::editValueAt(size_t index) {
+    return mVector.editItemAt(index).value;
+}
+
+template<typename KEY, typename VALUE> inline
+ssize_t KeyedVector<KEY,VALUE>::add(const KEY& key, const VALUE& value) {
+    return mVector.add( key_value_pair_t<KEY,VALUE>(key, value) );
+}
+
+template<typename KEY, typename VALUE> inline
+ssize_t KeyedVector<KEY,VALUE>::replaceValueFor(const KEY& key, const VALUE& value) {
+    key_value_pair_t<KEY,VALUE> pair(key, value);
+    mVector.remove(pair);
+    return mVector.add(pair);
+}
+
+template<typename KEY, typename VALUE> inline
+ssize_t KeyedVector<KEY,VALUE>::replaceValueAt(size_t index, const VALUE& item) {
+    if (index<size()) {
+        mVector.editItemAt(index).value = item;
+        return index;
+    }
+    return BAD_INDEX;
+}
+
+template<typename KEY, typename VALUE> inline
+ssize_t KeyedVector<KEY,VALUE>::removeItem(const KEY& key) {
+    return mVector.remove(key_value_pair_t<KEY,VALUE>(key));
+}
+
+template<typename KEY, typename VALUE> inline
+ssize_t KeyedVector<KEY, VALUE>::removeItemsAt(size_t index, size_t count) {
+    return mVector.removeItemsAt(index, count);
+}
+
+// ---------------------------------------------------------------------------
+
+template<typename KEY, typename VALUE> inline
+DefaultKeyedVector<KEY,VALUE>::DefaultKeyedVector(const VALUE& defValue)
+    : mDefault(defValue)
+{
+}
+
+template<typename KEY, typename VALUE> inline
+const VALUE& DefaultKeyedVector<KEY,VALUE>::valueFor(const KEY& key) const {
+    ssize_t i = this->indexOfKey(key);
+    return i >= 0 ? KeyedVector<KEY,VALUE>::valueAt(i) : mDefault;
+}
+
+}; // namespace android
+
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_KEYED_VECTOR_H
diff --git a/package/utils/adbd/src/include/utils/LinearAllocator.h b/package/utils/adbd/src/include/utils/LinearAllocator.h
new file mode 100644
index 0000000..4772bc8
--- /dev/null
+++ b/package/utils/adbd/src/include/utils/LinearAllocator.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ANDROID_LINEARALLOCATOR_H
+#define ANDROID_LINEARALLOCATOR_H
+
+#include <stddef.h>
+
+namespace android {
+
+/**
+ * A memory manager that internally allocates multi-kbyte buffers for placing objects in. It avoids
+ * the overhead of malloc when many objects are allocated. It is most useful when creating many
+ * small objects with a similar lifetime, and doesn't add significant overhead for large
+ * allocations.
+ */
+class LinearAllocator {
+public:
+    LinearAllocator();
+    ~LinearAllocator();
+
+    /**
+     * Reserves and returns a region of memory of at least size 'size', aligning as needed.
+     * Typically this is used in an object's overridden new() method or as a replacement for malloc.
+     *
+     * The lifetime of the returned buffers is tied to that of the LinearAllocator. If calling
+     * delete() on an object stored in a buffer is needed, it should be overridden to use
+     * rewindIfLastAlloc()
+     */
+    void* alloc(size_t size);
+
+    /**
+     * Attempt to deallocate the given buffer, with the LinearAllocator attempting to rewind its
+     * state if possible. No destructors are called.
+     */
+    void rewindIfLastAlloc(void* ptr, size_t allocSize);
+
+    /**
+     * Dump memory usage statistics to the log (allocated and wasted space)
+     */
+    void dumpMemoryStats(const char* prefix = "");
+
+    /**
+     * The number of bytes used for buffers allocated in the LinearAllocator (does not count space
+     * wasted)
+     */
+    size_t usedSize() const { return mTotalAllocated - mWastedSpace; }
+
+private:
+    LinearAllocator(const LinearAllocator& other);
+
+    class Page;
+
+    Page* newPage(size_t pageSize);
+    bool fitsInCurrentPage(size_t size);
+    void ensureNext(size_t size);
+    void* start(Page *p);
+    void* end(Page* p);
+
+    size_t mPageSize;
+    size_t mMaxAllocSize;
+    void* mNext;
+    Page* mCurrentPage;
+    Page* mPages;
+
+    // Memory usage tracking
+    size_t mTotalAllocated;
+    size_t mWastedSpace;
+    size_t mPageCount;
+    size_t mDedicatedPageCount;
+};
+
+}; // namespace android
+
+#endif // ANDROID_LINEARALLOCATOR_H
diff --git a/package/utils/adbd/src/include/utils/LinearTransform.h b/package/utils/adbd/src/include/utils/LinearTransform.h
new file mode 100644
index 0000000..04cb355
--- /dev/null
+++ b/package/utils/adbd/src/include/utils/LinearTransform.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2011 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 _LIBS_UTILS_LINEAR_TRANSFORM_H
+#define _LIBS_UTILS_LINEAR_TRANSFORM_H
+
+#include <stdint.h>
+
+namespace android {
+
+// LinearTransform defines a structure which hold the definition of a
+// transformation from single dimensional coordinate system A into coordinate
+// system B (and back again).  Values in A and in B are 64 bit, the linear
+// scale factor is expressed as a rational number using two 32 bit values.
+//
+// Specifically, let
+// f(a) = b
+// F(b) = f^-1(b) = a
+// then
+//
+// f(a) = (((a - a_zero) * a_to_b_numer) / a_to_b_denom) + b_zero;
+//
+// and
+//
+// F(b) = (((b - b_zero) * a_to_b_denom) / a_to_b_numer) + a_zero;
+//
+struct LinearTransform {
+  int64_t  a_zero;
+  int64_t  b_zero;
+  int32_t  a_to_b_numer;
+  uint32_t a_to_b_denom;
+
+  // Transform from A->B
+  // Returns true on success, or false in the case of a singularity or an
+  // overflow.
+  bool doForwardTransform(int64_t a_in, int64_t* b_out) const;
+
+  // Transform from B->A
+  // Returns true on success, or false in the case of a singularity or an
+  // overflow.
+  bool doReverseTransform(int64_t b_in, int64_t* a_out) const;
+
+  // Helpers which will reduce the fraction N/D using Euclid's method.
+  template <class T> static void reduce(T* N, T* D);
+  static void reduce(int32_t* N, uint32_t* D);
+};
+
+
+}
+
+#endif  // _LIBS_UTILS_LINEAR_TRANSFORM_H
diff --git a/package/utils/adbd/src/include/utils/List.h b/package/utils/adbd/src/include/utils/List.h
new file mode 100644
index 0000000..403cd7f
--- /dev/null
+++ b/package/utils/adbd/src/include/utils/List.h
@@ -0,0 +1,332 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+//
+// Templated list class.  Normally we'd use STL, but we don't have that.
+// This class mimics STL's interfaces.
+//
+// Objects are copied into the list with the '=' operator or with copy-
+// construction, so if the compiler's auto-generated versions won't work for
+// you, define your own.
+//
+// The only class you want to use from here is "List".
+//
+#ifndef _LIBS_UTILS_LIST_H
+#define _LIBS_UTILS_LIST_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+namespace android {
+
+/*
+ * Doubly-linked list.  Instantiate with "List<MyClass> myList".
+ *
+ * Objects added to the list are copied using the assignment operator,
+ * so this must be defined.
+ */
+template<typename T> 
+class List 
+{
+protected:
+    /*
+     * One element in the list.
+     */
+    class _Node {
+    public:
+        explicit _Node(const T& val) : mVal(val) {}
+        ~_Node() {}
+        inline T& getRef() { return mVal; }
+        inline const T& getRef() const { return mVal; }
+        inline _Node* getPrev() const { return mpPrev; }
+        inline _Node* getNext() const { return mpNext; }
+        inline void setVal(const T& val) { mVal = val; }
+        inline void setPrev(_Node* ptr) { mpPrev = ptr; }
+        inline void setNext(_Node* ptr) { mpNext = ptr; }
+    private:
+        friend class List;
+        friend class _ListIterator;
+        T           mVal;
+        _Node*      mpPrev;
+        _Node*      mpNext;
+    };
+
+    /*
+     * Iterator for walking through the list.
+     */
+    
+    template <typename TYPE>
+    struct CONST_ITERATOR {
+        typedef _Node const * NodePtr;
+        typedef const TYPE Type;
+    };
+    
+    template <typename TYPE>
+    struct NON_CONST_ITERATOR {
+        typedef _Node* NodePtr;
+        typedef TYPE Type;
+    };
+    
+    template<
+        typename U,
+        template <class> class Constness
+    > 
+    class _ListIterator {
+        typedef _ListIterator<U, Constness>     _Iter;
+        typedef typename Constness<U>::NodePtr  _NodePtr;
+        typedef typename Constness<U>::Type     _Type;
+
+        explicit _ListIterator(_NodePtr ptr) : mpNode(ptr) {}
+
+    public:
+        _ListIterator() {}
+        _ListIterator(const _Iter& rhs) : mpNode(rhs.mpNode) {}
+        ~_ListIterator() {}
+        
+        // this will handle conversions from iterator to const_iterator
+        // (and also all convertible iterators)
+        // Here, in this implementation, the iterators can be converted
+        // if the nodes can be converted
+        template<typename V> explicit 
+        _ListIterator(const V& rhs) : mpNode(rhs.mpNode) {}
+        
+
+        /*
+         * Dereference operator.  Used to get at the juicy insides.
+         */
+        _Type& operator*() const { return mpNode->getRef(); }
+        _Type* operator->() const { return &(mpNode->getRef()); }
+
+        /*
+         * Iterator comparison.
+         */
+        inline bool operator==(const _Iter& right) const { 
+            return mpNode == right.mpNode; }
+        
+        inline bool operator!=(const _Iter& right) const { 
+            return mpNode != right.mpNode; }
+
+        /*
+         * handle comparisons between iterator and const_iterator
+         */
+        template<typename OTHER>
+        inline bool operator==(const OTHER& right) const { 
+            return mpNode == right.mpNode; }
+        
+        template<typename OTHER>
+        inline bool operator!=(const OTHER& right) const { 
+            return mpNode != right.mpNode; }
+
+        /*
+         * Incr/decr, used to move through the list.
+         */
+        inline _Iter& operator++() {     // pre-increment
+            mpNode = mpNode->getNext();
+            return *this;
+        }
+        const _Iter operator++(int) {    // post-increment
+            _Iter tmp(*this);
+            mpNode = mpNode->getNext();
+            return tmp;
+        }
+        inline _Iter& operator--() {     // pre-increment
+            mpNode = mpNode->getPrev();
+            return *this;
+        }
+        const _Iter operator--(int) {   // post-increment
+            _Iter tmp(*this);
+            mpNode = mpNode->getPrev();
+            return tmp;
+        }
+
+        inline _NodePtr getNode() const { return mpNode; }
+
+        _NodePtr mpNode;    /* should be private, but older gcc fails */
+    private:
+        friend class List;
+    };
+
+public:
+    List() {
+        prep();
+    }
+    List(const List<T>& src) {      // copy-constructor
+        prep();
+        insert(begin(), src.begin(), src.end());
+    }
+    virtual ~List() {
+        clear();
+        delete[] (unsigned char*) mpMiddle;
+    }
+
+    typedef _ListIterator<T, NON_CONST_ITERATOR> iterator;
+    typedef _ListIterator<T, CONST_ITERATOR> const_iterator;
+
+    List<T>& operator=(const List<T>& right);
+
+    /* returns true if the list is empty */
+    inline bool empty() const { return mpMiddle->getNext() == mpMiddle; }
+
+    /* return #of elements in list */
+    size_t size() const {
+        return size_t(distance(begin(), end()));
+    }
+
+    /*
+     * Return the first element or one past the last element.  The
+     * _Node* we're returning is converted to an "iterator" by a
+     * constructor in _ListIterator.
+     */
+    inline iterator begin() { 
+        return iterator(mpMiddle->getNext()); 
+    }
+    inline const_iterator begin() const { 
+        return const_iterator(const_cast<_Node const*>(mpMiddle->getNext())); 
+    }
+    inline iterator end() { 
+        return iterator(mpMiddle); 
+    }
+    inline const_iterator end() const { 
+        return const_iterator(const_cast<_Node const*>(mpMiddle)); 
+    }
+
+    /* add the object to the head or tail of the list */
+    void push_front(const T& val) { insert(begin(), val); }
+    void push_back(const T& val) { insert(end(), val); }
+
+    /* insert before the current node; returns iterator at new node */
+    iterator insert(iterator posn, const T& val) 
+    {
+        _Node* newNode = new _Node(val);        // alloc & copy-construct
+        newNode->setNext(posn.getNode());
+        newNode->setPrev(posn.getNode()->getPrev());
+        posn.getNode()->getPrev()->setNext(newNode);
+        posn.getNode()->setPrev(newNode);
+        return iterator(newNode);
+    }
+
+    /* insert a range of elements before the current node */
+    void insert(iterator posn, const_iterator first, const_iterator last) {
+        for ( ; first != last; ++first)
+            insert(posn, *first);
+    }
+
+    /* remove one entry; returns iterator at next node */
+    iterator erase(iterator posn) {
+        _Node* pNext = posn.getNode()->getNext();
+        _Node* pPrev = posn.getNode()->getPrev();
+        pPrev->setNext(pNext);
+        pNext->setPrev(pPrev);
+        delete posn.getNode();
+        return iterator(pNext);
+    }
+
+    /* remove a range of elements */
+    iterator erase(iterator first, iterator last) {
+        while (first != last)
+            erase(first++);     // don't erase than incr later!
+        return iterator(last);
+    }
+
+    /* remove all contents of the list */
+    void clear() {
+        _Node* pCurrent = mpMiddle->getNext();
+        _Node* pNext;
+
+        while (pCurrent != mpMiddle) {
+            pNext = pCurrent->getNext();
+            delete pCurrent;
+            pCurrent = pNext;
+        }
+        mpMiddle->setPrev(mpMiddle);
+        mpMiddle->setNext(mpMiddle);
+    }
+
+    /*
+     * Measure the distance between two iterators.  On exist, "first"
+     * will be equal to "last".  The iterators must refer to the same
+     * list.
+     *
+     * FIXME: This is actually a generic iterator function. It should be a 
+     * template function at the top-level with specializations for things like
+     * vector<>, which can just do pointer math). Here we limit it to
+     * _ListIterator of the same type but different constness.
+     */
+    template<
+        typename U,
+        template <class> class CL,
+        template <class> class CR
+    > 
+    ptrdiff_t distance(
+            _ListIterator<U, CL> first, _ListIterator<U, CR> last) const 
+    {
+        ptrdiff_t count = 0;
+        while (first != last) {
+            ++first;
+            ++count;
+        }
+        return count;
+    }
+
+private:
+    /*
+     * I want a _Node but don't need it to hold valid data.  More
+     * to the point, I don't want T's constructor to fire, since it
+     * might have side-effects or require arguments.  So, we do this
+     * slightly uncouth storage alloc.
+     */
+    void prep() {
+        mpMiddle = (_Node*) new unsigned char[sizeof(_Node)];
+        mpMiddle->setPrev(mpMiddle);
+        mpMiddle->setNext(mpMiddle);
+    }
+
+    /*
+     * This node plays the role of "pointer to head" and "pointer to tail".
+     * It sits in the middle of a circular list of nodes.  The iterator
+     * runs around the circle until it encounters this one.
+     */
+    _Node*      mpMiddle;
+};
+
+/*
+ * Assignment operator.
+ *
+ * The simplest way to do this would be to clear out the target list and
+ * fill it with the source.  However, we can speed things along by
+ * re-using existing elements.
+ */
+template<class T>
+List<T>& List<T>::operator=(const List<T>& right)
+{
+    if (this == &right)
+        return *this;       // self-assignment
+    iterator firstDst = begin();
+    iterator lastDst = end();
+    const_iterator firstSrc = right.begin();
+    const_iterator lastSrc = right.end();
+    while (firstSrc != lastSrc && firstDst != lastDst)
+        *firstDst++ = *firstSrc++;
+    if (firstSrc == lastSrc)        // ran out of elements in source?
+        erase(firstDst, lastDst);   // yes, erase any extras
+    else
+        insert(lastDst, firstSrc, lastSrc);     // copy remaining over
+    return *this;
+}
+
+}; // namespace android
+
+#endif // _LIBS_UTILS_LIST_H
diff --git a/package/utils/adbd/src/include/utils/Log.h b/package/utils/adbd/src/include/utils/Log.h
new file mode 100644
index 0000000..4259c86
--- /dev/null
+++ b/package/utils/adbd/src/include/utils/Log.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+//
+// C/C++ logging functions.  See the logging documentation for API details.
+//
+// We'd like these to be available from C code (in case we import some from
+// somewhere), so this has a C interface.
+//
+// The output will be correct when the log file is shared between multiple
+// threads and/or multiple processes so long as the operating system
+// supports O_APPEND.  These calls have mutex-protected data structures
+// and so are NOT reentrant.  Do not use LOG in a signal handler.
+//
+#ifndef _LIBS_UTILS_LOG_H
+#define _LIBS_UTILS_LOG_H
+
+#include <cutils/log.h>
+#include <sys/types.h>
+
+#ifdef __cplusplus
+
+namespace android {
+
+/*
+ * A very simple utility that yells in the log when an operation takes too long.
+ */
+class LogIfSlow {
+public:
+    LogIfSlow(const char* tag, android_LogPriority priority,
+            int timeoutMillis, const char* message);
+    ~LogIfSlow();
+
+private:
+    const char* const mTag;
+    const android_LogPriority mPriority;
+    const int mTimeoutMillis;
+    const char* const mMessage;
+    const int64_t mStart;
+};
+
+/*
+ * Writes the specified debug log message if this block takes longer than the
+ * specified number of milliseconds to run.  Includes the time actually taken.
+ *
+ * {
+ *     ALOGD_IF_SLOW(50, "Excessive delay doing something.");
+ *     doSomething();
+ * }
+ */
+#define ALOGD_IF_SLOW(timeoutMillis, message) \
+    android::LogIfSlow _logIfSlow(LOG_TAG, ANDROID_LOG_DEBUG, timeoutMillis, message);
+
+} // namespace android
+
+#endif // __cplusplus
+
+#endif // _LIBS_UTILS_LOG_H
diff --git a/package/utils/adbd/src/include/utils/Looper.h b/package/utils/adbd/src/include/utils/Looper.h
new file mode 100644
index 0000000..15c9891
--- /dev/null
+++ b/package/utils/adbd/src/include/utils/Looper.h
@@ -0,0 +1,477 @@
+/*
+ * Copyright (C) 2010 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 UTILS_LOOPER_H
+#define UTILS_LOOPER_H
+
+#include <utils/threads.h>
+#include <utils/RefBase.h>
+#include <utils/KeyedVector.h>
+#include <utils/Timers.h>
+
+#include <sys/epoll.h>
+
+namespace android {
+
+/*
+ * NOTE: Since Looper is used to implement the NDK ALooper, the Looper
+ * enums and the signature of Looper_callbackFunc need to align with
+ * that implementation.
+ */
+
+/**
+ * For callback-based event loops, this is the prototype of the function
+ * that is called when a file descriptor event occurs.
+ * It is given the file descriptor it is associated with,
+ * a bitmask of the poll events that were triggered (typically EVENT_INPUT),
+ * and the data pointer that was originally supplied.
+ *
+ * Implementations should return 1 to continue receiving callbacks, or 0
+ * to have this file descriptor and callback unregistered from the looper.
+ */
+typedef int (*Looper_callbackFunc)(int fd, int events, void* data);
+
+/**
+ * A message that can be posted to a Looper.
+ */
+struct Message {
+    Message() : what(0) { }
+    Message(int what) : what(what) { }
+
+    /* The message type. (interpretation is left up to the handler) */
+    int what;
+};
+
+
+/**
+ * Interface for a Looper message handler.
+ *
+ * The Looper holds a strong reference to the message handler whenever it has
+ * a message to deliver to it.  Make sure to call Looper::removeMessages
+ * to remove any pending messages destined for the handler so that the handler
+ * can be destroyed.
+ */
+class MessageHandler : public virtual RefBase {
+protected:
+    virtual ~MessageHandler() { }
+
+public:
+    /**
+     * Handles a message.
+     */
+    virtual void handleMessage(const Message& message) = 0;
+};
+
+
+/**
+ * A simple proxy that holds a weak reference to a message handler.
+ */
+class WeakMessageHandler : public MessageHandler {
+protected:
+    virtual ~WeakMessageHandler();
+
+public:
+    WeakMessageHandler(const wp<MessageHandler>& handler);
+    virtual void handleMessage(const Message& message);
+
+private:
+    wp<MessageHandler> mHandler;
+};
+
+
+/**
+ * A looper callback.
+ */
+class LooperCallback : public virtual RefBase {
+protected:
+    virtual ~LooperCallback() { }
+
+public:
+    /**
+     * Handles a poll event for the given file descriptor.
+     * It is given the file descriptor it is associated with,
+     * a bitmask of the poll events that were triggered (typically EVENT_INPUT),
+     * and the data pointer that was originally supplied.
+     *
+     * Implementations should return 1 to continue receiving callbacks, or 0
+     * to have this file descriptor and callback unregistered from the looper.
+     */
+    virtual int handleEvent(int fd, int events, void* data) = 0;
+};
+
+/**
+ * Wraps a Looper_callbackFunc function pointer.
+ */
+class SimpleLooperCallback : public LooperCallback {
+protected:
+    virtual ~SimpleLooperCallback();
+
+public:
+    SimpleLooperCallback(Looper_callbackFunc callback);
+    virtual int handleEvent(int fd, int events, void* data);
+
+private:
+    Looper_callbackFunc mCallback;
+};
+
+/**
+ * A polling loop that supports monitoring file descriptor events, optionally
+ * using callbacks.  The implementation uses epoll() internally.
+ *
+ * A looper can be associated with a thread although there is no requirement that it must be.
+ */
+class Looper : public RefBase {
+protected:
+    virtual ~Looper();
+
+public:
+    enum {
+        /**
+         * Result from Looper_pollOnce() and Looper_pollAll():
+         * The poll was awoken using wake() before the timeout expired
+         * and no callbacks were executed and no other file descriptors were ready.
+         */
+        POLL_WAKE = -1,
+
+        /**
+         * Result from Looper_pollOnce() and Looper_pollAll():
+         * One or more callbacks were executed.
+         */
+        POLL_CALLBACK = -2,
+
+        /**
+         * Result from Looper_pollOnce() and Looper_pollAll():
+         * The timeout expired.
+         */
+        POLL_TIMEOUT = -3,
+
+        /**
+         * Result from Looper_pollOnce() and Looper_pollAll():
+         * An error occurred.
+         */
+        POLL_ERROR = -4,
+    };
+
+    /**
+     * Flags for file descriptor events that a looper can monitor.
+     *
+     * These flag bits can be combined to monitor multiple events at once.
+     */
+    enum {
+        /**
+         * The file descriptor is available for read operations.
+         */
+        EVENT_INPUT = 1 << 0,
+
+        /**
+         * The file descriptor is available for write operations.
+         */
+        EVENT_OUTPUT = 1 << 1,
+
+        /**
+         * The file descriptor has encountered an error condition.
+         *
+         * The looper always sends notifications about errors; it is not necessary
+         * to specify this event flag in the requested event set.
+         */
+        EVENT_ERROR = 1 << 2,
+
+        /**
+         * The file descriptor was hung up.
+         * For example, indicates that the remote end of a pipe or socket was closed.
+         *
+         * The looper always sends notifications about hangups; it is not necessary
+         * to specify this event flag in the requested event set.
+         */
+        EVENT_HANGUP = 1 << 3,
+
+        /**
+         * The file descriptor is invalid.
+         * For example, the file descriptor was closed prematurely.
+         *
+         * The looper always sends notifications about invalid file descriptors; it is not necessary
+         * to specify this event flag in the requested event set.
+         */
+        EVENT_INVALID = 1 << 4,
+    };
+
+    enum {
+        /**
+         * Option for Looper_prepare: this looper will accept calls to
+         * Looper_addFd() that do not have a callback (that is provide NULL
+         * for the callback).  In this case the caller of Looper_pollOnce()
+         * or Looper_pollAll() MUST check the return from these functions to
+         * discover when data is available on such fds and process it.
+         */
+        PREPARE_ALLOW_NON_CALLBACKS = 1<<0
+    };
+
+    /**
+     * Creates a looper.
+     *
+     * If allowNonCallbaks is true, the looper will allow file descriptors to be
+     * registered without associated callbacks.  This assumes that the caller of
+     * pollOnce() is prepared to handle callback-less events itself.
+     */
+    Looper(bool allowNonCallbacks);
+
+    /**
+     * Returns whether this looper instance allows the registration of file descriptors
+     * using identifiers instead of callbacks.
+     */
+    bool getAllowNonCallbacks() const;
+
+    /**
+     * Waits for events to be available, with optional timeout in milliseconds.
+     * Invokes callbacks for all file descriptors on which an event occurred.
+     *
+     * If the timeout is zero, returns immediately without blocking.
+     * If the timeout is negative, waits indefinitely until an event appears.
+     *
+     * Returns POLL_WAKE if the poll was awoken using wake() before
+     * the timeout expired and no callbacks were invoked and no other file
+     * descriptors were ready.
+     *
+     * Returns POLL_CALLBACK if one or more callbacks were invoked.
+     *
+     * Returns POLL_TIMEOUT if there was no data before the given
+     * timeout expired.
+     *
+     * Returns POLL_ERROR if an error occurred.
+     *
+     * Returns a value >= 0 containing an identifier if its file descriptor has data
+     * and it has no callback function (requiring the caller here to handle it).
+     * In this (and only this) case outFd, outEvents and outData will contain the poll
+     * events and data associated with the fd, otherwise they will be set to NULL.
+     *
+     * This method does not return until it has finished invoking the appropriate callbacks
+     * for all file descriptors that were signalled.
+     */
+    int pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData);
+    inline int pollOnce(int timeoutMillis) {
+        return pollOnce(timeoutMillis, NULL, NULL, NULL);
+    }
+
+    /**
+     * Like pollOnce(), but performs all pending callbacks until all
+     * data has been consumed or a file descriptor is available with no callback.
+     * This function will never return POLL_CALLBACK.
+     */
+    int pollAll(int timeoutMillis, int* outFd, int* outEvents, void** outData);
+    inline int pollAll(int timeoutMillis) {
+        return pollAll(timeoutMillis, NULL, NULL, NULL);
+    }
+
+    /**
+     * Wakes the poll asynchronously.
+     *
+     * This method can be called on any thread.
+     * This method returns immediately.
+     */
+    void wake();
+
+    /**
+     * Adds a new file descriptor to be polled by the looper.
+     * If the same file descriptor was previously added, it is replaced.
+     *
+     * "fd" is the file descriptor to be added.
+     * "ident" is an identifier for this event, which is returned from pollOnce().
+     * The identifier must be >= 0, or POLL_CALLBACK if providing a non-NULL callback.
+     * "events" are the poll events to wake up on.  Typically this is EVENT_INPUT.
+     * "callback" is the function to call when there is an event on the file descriptor.
+     * "data" is a private data pointer to supply to the callback.
+     *
+     * There are two main uses of this function:
+     *
+     * (1) If "callback" is non-NULL, then this function will be called when there is
+     * data on the file descriptor.  It should execute any events it has pending,
+     * appropriately reading from the file descriptor.  The 'ident' is ignored in this case.
+     *
+     * (2) If "callback" is NULL, the 'ident' will be returned by Looper_pollOnce
+     * when its file descriptor has data available, requiring the caller to take
+     * care of processing it.
+     *
+     * Returns 1 if the file descriptor was added, 0 if the arguments were invalid.
+     *
+     * This method can be called on any thread.
+     * This method may block briefly if it needs to wake the poll.
+     *
+     * The callback may either be specified as a bare function pointer or as a smart
+     * pointer callback object.  The smart pointer should be preferred because it is
+     * easier to avoid races when the callback is removed from a different thread.
+     * See removeFd() for details.
+     */
+    int addFd(int fd, int ident, int events, Looper_callbackFunc callback, void* data);
+    int addFd(int fd, int ident, int events, const sp<LooperCallback>& callback, void* data);
+
+    /**
+     * Removes a previously added file descriptor from the looper.
+     *
+     * When this method returns, it is safe to close the file descriptor since the looper
+     * will no longer have a reference to it.  However, it is possible for the callback to
+     * already be running or for it to run one last time if the file descriptor was already
+     * signalled.  Calling code is responsible for ensuring that this case is safely handled.
+     * For example, if the callback takes care of removing itself during its own execution either
+     * by returning 0 or by calling this method, then it can be guaranteed to not be invoked
+     * again at any later time unless registered anew.
+     *
+     * A simple way to avoid this problem is to use the version of addFd() that takes
+     * a sp<LooperCallback> instead of a bare function pointer.  The LooperCallback will
+     * be released at the appropriate time by the Looper.
+     *
+     * Returns 1 if the file descriptor was removed, 0 if none was previously registered.
+     *
+     * This method can be called on any thread.
+     * This method may block briefly if it needs to wake the poll.
+     */
+    int removeFd(int fd);
+
+    /**
+     * Enqueues a message to be processed by the specified handler.
+     *
+     * The handler must not be null.
+     * This method can be called on any thread.
+     */
+    void sendMessage(const sp<MessageHandler>& handler, const Message& message);
+
+    /**
+     * Enqueues a message to be processed by the specified handler after all pending messages
+     * after the specified delay.
+     *
+     * The time delay is specified in uptime nanoseconds.
+     * The handler must not be null.
+     * This method can be called on any thread.
+     */
+    void sendMessageDelayed(nsecs_t uptimeDelay, const sp<MessageHandler>& handler,
+            const Message& message);
+
+    /**
+     * Enqueues a message to be processed by the specified handler after all pending messages
+     * at the specified time.
+     *
+     * The time is specified in uptime nanoseconds.
+     * The handler must not be null.
+     * This method can be called on any thread.
+     */
+    void sendMessageAtTime(nsecs_t uptime, const sp<MessageHandler>& handler,
+            const Message& message);
+
+    /**
+     * Removes all messages for the specified handler from the queue.
+     *
+     * The handler must not be null.
+     * This method can be called on any thread.
+     */
+    void removeMessages(const sp<MessageHandler>& handler);
+
+    /**
+     * Removes all messages of a particular type for the specified handler from the queue.
+     *
+     * The handler must not be null.
+     * This method can be called on any thread.
+     */
+    void removeMessages(const sp<MessageHandler>& handler, int what);
+
+    /**
+     * Return whether this looper's thread is currently idling -- that is, whether it
+     * stopped waiting for more work to do.  Note that this is intrinsically racy, since
+     * its state can change before you get the result back.
+     */
+    bool isIdling() const;
+
+    /**
+     * Prepares a looper associated with the calling thread, and returns it.
+     * If the thread already has a looper, it is returned.  Otherwise, a new
+     * one is created, associated with the thread, and returned.
+     *
+     * The opts may be PREPARE_ALLOW_NON_CALLBACKS or 0.
+     */
+    static sp<Looper> prepare(int opts);
+
+    /**
+     * Sets the given looper to be associated with the calling thread.
+     * If another looper is already associated with the thread, it is replaced.
+     *
+     * If "looper" is NULL, removes the currently associated looper.
+     */
+    static void setForThread(const sp<Looper>& looper);
+
+    /**
+     * Returns the looper associated with the calling thread, or NULL if
+     * there is not one.
+     */
+    static sp<Looper> getForThread();
+
+private:
+    struct Request {
+        int fd;
+        int ident;
+        sp<LooperCallback> callback;
+        void* data;
+    };
+
+    struct Response {
+        int events;
+        Request request;
+    };
+
+    struct MessageEnvelope {
+        MessageEnvelope() : uptime(0) { }
+
+        MessageEnvelope(nsecs_t uptime, const sp<MessageHandler> handler,
+                const Message& message) : uptime(uptime), handler(handler), message(message) {
+        }
+
+        nsecs_t uptime;
+        sp<MessageHandler> handler;
+        Message message;
+    };
+
+    const bool mAllowNonCallbacks; // immutable
+
+    int mWakeReadPipeFd;  // immutable
+    int mWakeWritePipeFd; // immutable
+    Mutex mLock;
+
+    Vector<MessageEnvelope> mMessageEnvelopes; // guarded by mLock
+    bool mSendingMessage; // guarded by mLock
+
+    // Whether we are currently waiting for work.  Not protected by a lock,
+    // any use of it is racy anyway.
+    volatile bool mIdling;
+
+    int mEpollFd; // immutable
+
+    // Locked list of file descriptor monitoring requests.
+    KeyedVector<int, Request> mRequests;  // guarded by mLock
+
+    // This state is only used privately by pollOnce and does not require a lock since
+    // it runs on a single thread.
+    Vector<Response> mResponses;
+    size_t mResponseIndex;
+    nsecs_t mNextMessageUptime; // set to LLONG_MAX when none
+
+    int pollInner(int timeoutMillis);
+    void awoken();
+    void pushResponse(int events, const Request& request);
+
+    static void initTLSKey();
+    static void threadDestructor(void *st);
+};
+
+} // namespace android
+
+#endif // UTILS_LOOPER_H
diff --git a/package/utils/adbd/src/include/utils/LruCache.h b/package/utils/adbd/src/include/utils/LruCache.h
new file mode 100644
index 0000000..cd9d7f9
--- /dev/null
+++ b/package/utils/adbd/src/include/utils/LruCache.h
@@ -0,0 +1,250 @@
+/*
+ * Copyright (C) 2012 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 ANDROID_UTILS_LRU_CACHE_H
+#define ANDROID_UTILS_LRU_CACHE_H
+
+#include <UniquePtr.h>
+#include <utils/BasicHashtable.h>
+
+namespace android {
+
+/**
+ * GenerationCache callback used when an item is removed
+ */
+template<typename EntryKey, typename EntryValue>
+class OnEntryRemoved {
+public:
+    virtual ~OnEntryRemoved() { };
+    virtual void operator()(EntryKey& key, EntryValue& value) = 0;
+}; // class OnEntryRemoved
+
+template <typename TKey, typename TValue>
+class LruCache {
+public:
+    explicit LruCache(uint32_t maxCapacity);
+
+    enum Capacity {
+        kUnlimitedCapacity,
+    };
+
+    void setOnEntryRemovedListener(OnEntryRemoved<TKey, TValue>* listener);
+    size_t size() const;
+    const TValue& get(const TKey& key);
+    bool put(const TKey& key, const TValue& value);
+    bool remove(const TKey& key);
+    bool removeOldest();
+    void clear();
+    const TValue& peekOldestValue();
+
+    class Iterator {
+    public:
+        Iterator(const LruCache<TKey, TValue>& cache): mCache(cache), mIndex(-1) {
+        }
+
+        bool next() {
+            mIndex = mCache.mTable->next(mIndex);
+            return (ssize_t)mIndex != -1;
+        }
+
+        size_t index() const {
+            return mIndex;
+        }
+
+        const TValue& value() const {
+            return mCache.mTable->entryAt(mIndex).value;
+        }
+
+        const TKey& key() const {
+            return mCache.mTable->entryAt(mIndex).key;
+        }
+    private:
+        const LruCache<TKey, TValue>& mCache;
+        size_t mIndex;
+    };
+
+private:
+    LruCache(const LruCache& that);  // disallow copy constructor
+
+    struct Entry {
+        TKey key;
+        TValue value;
+        Entry* parent;
+        Entry* child;
+
+        Entry(TKey key_, TValue value_) : key(key_), value(value_), parent(NULL), child(NULL) {
+        }
+        const TKey& getKey() const { return key; }
+    };
+
+    void attachToCache(Entry& entry);
+    void detachFromCache(Entry& entry);
+    void rehash(size_t newCapacity);
+
+    UniquePtr<BasicHashtable<TKey, Entry> > mTable;
+    OnEntryRemoved<TKey, TValue>* mListener;
+    Entry* mOldest;
+    Entry* mYoungest;
+    uint32_t mMaxCapacity;
+    TValue mNullValue;
+};
+
+// Implementation is here, because it's fully templated
+template <typename TKey, typename TValue>
+LruCache<TKey, TValue>::LruCache(uint32_t maxCapacity)
+    : mTable(new BasicHashtable<TKey, Entry>)
+    , mListener(NULL)
+    , mOldest(NULL)
+    , mYoungest(NULL)
+    , mMaxCapacity(maxCapacity)
+    , mNullValue(NULL) {
+};
+
+template<typename K, typename V>
+void LruCache<K, V>::setOnEntryRemovedListener(OnEntryRemoved<K, V>* listener) {
+    mListener = listener;
+}
+
+template <typename TKey, typename TValue>
+size_t LruCache<TKey, TValue>::size() const {
+    return mTable->size();
+}
+
+template <typename TKey, typename TValue>
+const TValue& LruCache<TKey, TValue>::get(const TKey& key) {
+    hash_t hash = hash_type(key);
+    ssize_t index = mTable->find(-1, hash, key);
+    if (index == -1) {
+        return mNullValue;
+    }
+    Entry& entry = mTable->editEntryAt(index);
+    detachFromCache(entry);
+    attachToCache(entry);
+    return entry.value;
+}
+
+template <typename TKey, typename TValue>
+bool LruCache<TKey, TValue>::put(const TKey& key, const TValue& value) {
+    if (mMaxCapacity != kUnlimitedCapacity && size() >= mMaxCapacity) {
+        removeOldest();
+    }
+
+    hash_t hash = hash_type(key);
+    ssize_t index = mTable->find(-1, hash, key);
+    if (index >= 0) {
+        return false;
+    }
+    if (!mTable->hasMoreRoom()) {
+        rehash(mTable->capacity() * 2);
+    }
+
+    // Would it be better to initialize a blank entry and assign key, value?
+    Entry initEntry(key, value);
+    index = mTable->add(hash, initEntry);
+    Entry& entry = mTable->editEntryAt(index);
+    attachToCache(entry);
+    return true;
+}
+
+template <typename TKey, typename TValue>
+bool LruCache<TKey, TValue>::remove(const TKey& key) {
+    hash_t hash = hash_type(key);
+    ssize_t index = mTable->find(-1, hash, key);
+    if (index < 0) {
+        return false;
+    }
+    Entry& entry = mTable->editEntryAt(index);
+    if (mListener) {
+        (*mListener)(entry.key, entry.value);
+    }
+    detachFromCache(entry);
+    mTable->removeAt(index);
+    return true;
+}
+
+template <typename TKey, typename TValue>
+bool LruCache<TKey, TValue>::removeOldest() {
+    if (mOldest != NULL) {
+        return remove(mOldest->key);
+        // TODO: should probably abort if false
+    }
+    return false;
+}
+
+template <typename TKey, typename TValue>
+const TValue& LruCache<TKey, TValue>::peekOldestValue() {
+    if (mOldest) {
+        return mOldest->value;
+    }
+    return mNullValue;
+}
+
+template <typename TKey, typename TValue>
+void LruCache<TKey, TValue>::clear() {
+    if (mListener) {
+        for (Entry* p = mOldest; p != NULL; p = p->child) {
+            (*mListener)(p->key, p->value);
+        }
+    }
+    mYoungest = NULL;
+    mOldest = NULL;
+    mTable->clear();
+}
+
+template <typename TKey, typename TValue>
+void LruCache<TKey, TValue>::attachToCache(Entry& entry) {
+    if (mYoungest == NULL) {
+        mYoungest = mOldest = &entry;
+    } else {
+        entry.parent = mYoungest;
+        mYoungest->child = &entry;
+        mYoungest = &entry;
+    }
+}
+
+template <typename TKey, typename TValue>
+void LruCache<TKey, TValue>::detachFromCache(Entry& entry) {
+    if (entry.parent != NULL) {
+        entry.parent->child = entry.child;
+    } else {
+        mOldest = entry.child;
+    }
+    if (entry.child != NULL) {
+        entry.child->parent = entry.parent;
+    } else {
+        mYoungest = entry.parent;
+    }
+
+    entry.parent = NULL;
+    entry.child = NULL;
+}
+
+template <typename TKey, typename TValue>
+void LruCache<TKey, TValue>::rehash(size_t newCapacity) {
+    UniquePtr<BasicHashtable<TKey, Entry> > oldTable(mTable.release());
+    Entry* oldest = mOldest;
+
+    mOldest = NULL;
+    mYoungest = NULL;
+    mTable.reset(new BasicHashtable<TKey, Entry>(newCapacity));
+    for (Entry* p = oldest; p != NULL; p = p->child) {
+        put(p->key, p->value);
+    }
+}
+
+}
+
+#endif // ANDROID_UTILS_LRU_CACHE_H
diff --git a/package/utils/adbd/src/include/utils/Mutex.h b/package/utils/adbd/src/include/utils/Mutex.h
new file mode 100644
index 0000000..dd201c8
--- /dev/null
+++ b/package/utils/adbd/src/include/utils/Mutex.h
@@ -0,0 +1,137 @@
+/*
+ * 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 _LIBS_UTILS_MUTEX_H
+#define _LIBS_UTILS_MUTEX_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <time.h>
+
+#if defined(HAVE_PTHREADS)
+# include <pthread.h>
+#endif
+
+#include <utils/Errors.h>
+
+// ---------------------------------------------------------------------------
+namespace android {
+// ---------------------------------------------------------------------------
+
+class Condition;
+
+/*
+ * Simple mutex class.  The implementation is system-dependent.
+ *
+ * The mutex must be unlocked by the thread that locked it.  They are not
+ * recursive, i.e. the same thread can't lock it multiple times.
+ */
+class Mutex {
+public:
+    enum {
+        PRIVATE = 0,
+        SHARED = 1
+    };
+    
+                Mutex();
+                Mutex(const char* name);
+                Mutex(int type, const char* name = NULL);
+                ~Mutex();
+
+    // lock or unlock the mutex
+    status_t    lock();
+    void        unlock();
+
+    // lock if possible; returns 0 on success, error otherwise
+    status_t    tryLock();
+
+    // Manages the mutex automatically. It'll be locked when Autolock is
+    // constructed and released when Autolock goes out of scope.
+    class Autolock {
+    public:
+        inline Autolock(Mutex& mutex) : mLock(mutex)  { mLock.lock(); }
+        inline Autolock(Mutex* mutex) : mLock(*mutex) { mLock.lock(); }
+        inline ~Autolock() { mLock.unlock(); }
+    private:
+        Mutex& mLock;
+    };
+
+private:
+    friend class Condition;
+    
+    // A mutex cannot be copied
+                Mutex(const Mutex&);
+    Mutex&      operator = (const Mutex&);
+    
+#if defined(HAVE_PTHREADS)
+    pthread_mutex_t mMutex;
+#else
+    void    _init();
+    void*   mState;
+#endif
+};
+
+// ---------------------------------------------------------------------------
+
+#if defined(HAVE_PTHREADS)
+
+inline Mutex::Mutex() {
+    pthread_mutex_init(&mMutex, NULL);
+}
+inline Mutex::Mutex(__attribute__((unused)) const char* name) {
+    pthread_mutex_init(&mMutex, NULL);
+}
+inline Mutex::Mutex(int type, __attribute__((unused)) const char* name) {
+    if (type == SHARED) {
+        pthread_mutexattr_t attr;
+        pthread_mutexattr_init(&attr);
+        pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
+        pthread_mutex_init(&mMutex, &attr);
+        pthread_mutexattr_destroy(&attr);
+    } else {
+        pthread_mutex_init(&mMutex, NULL);
+    }
+}
+inline Mutex::~Mutex() {
+    pthread_mutex_destroy(&mMutex);
+}
+inline status_t Mutex::lock() {
+    return -pthread_mutex_lock(&mMutex);
+}
+inline void Mutex::unlock() {
+    pthread_mutex_unlock(&mMutex);
+}
+inline status_t Mutex::tryLock() {
+    return -pthread_mutex_trylock(&mMutex);
+}
+
+#endif // HAVE_PTHREADS
+
+// ---------------------------------------------------------------------------
+
+/*
+ * Automatic mutex.  Declare one of these at the top of a function.
+ * When the function returns, it will go out of scope, and release the
+ * mutex.
+ */
+ 
+typedef Mutex::Autolock AutoMutex;
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+// ---------------------------------------------------------------------------
+
+#endif // _LIBS_UTILS_MUTEX_H
diff --git a/package/utils/adbd/src/include/utils/NativeHandle.h b/package/utils/adbd/src/include/utils/NativeHandle.h
new file mode 100644
index 0000000..b825168
--- /dev/null
+++ b/package/utils/adbd/src/include/utils/NativeHandle.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2014 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 ANDROID_NATIVE_HANDLE_H
+#define ANDROID_NATIVE_HANDLE_H
+
+#include <utils/RefBase.h>
+#include <utils/StrongPointer.h>
+
+typedef struct native_handle native_handle_t;
+
+namespace android {
+
+class NativeHandle: public LightRefBase<NativeHandle> {
+public:
+    // Create a refcounted wrapper around a native_handle_t, and declare
+    // whether the wrapper owns the handle (so that it should clean up the
+    // handle upon destruction) or not.
+    // If handle is NULL, no NativeHandle will be created.
+    static sp<NativeHandle> create(native_handle_t* handle, bool ownsHandle);
+
+    const native_handle_t* handle() const {
+        return mHandle;
+    }
+
+private:
+    // for access to the destructor
+    friend class LightRefBase<NativeHandle>;
+
+    NativeHandle(native_handle_t* handle, bool ownsHandle);
+    virtual ~NativeHandle();
+
+    native_handle_t* mHandle;
+    bool mOwnsHandle;
+
+    // non-copyable
+    NativeHandle(const NativeHandle&);
+    NativeHandle& operator=(const NativeHandle&);
+};
+
+} // namespace android
+
+#endif // ANDROID_NATIVE_HANDLE_H
diff --git a/package/utils/adbd/src/include/utils/Printer.h b/package/utils/adbd/src/include/utils/Printer.h
new file mode 100644
index 0000000..bb66287
--- /dev/null
+++ b/package/utils/adbd/src/include/utils/Printer.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2013 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 ANDROID_PRINTER_H
+#define ANDROID_PRINTER_H
+
+#include <android/log.h>
+
+namespace android {
+
+// Interface for printing to an arbitrary data stream
+class Printer {
+public:
+    // Print a new line specified by 'string'. \n is appended automatically.
+    // -- Assumes that the string has no new line in it.
+    virtual void printLine(const char* string = "") = 0;
+
+    // Print a new line specified by the format string. \n is appended automatically.
+    // -- Assumes that the resulting string has no new line in it.
+    virtual void printFormatLine(const char* format, ...) __attribute__((format (printf, 2, 3)));
+
+protected:
+    Printer();
+    virtual ~Printer();
+}; // class Printer
+
+// Print to logcat
+class LogPrinter : public Printer {
+public:
+    // Create a printer using the specified logcat and log priority
+    // - Unless ignoreBlankLines is false, print blank lines to logcat
+    // (Note that the default ALOG behavior is to ignore blank lines)
+    LogPrinter(const char* logtag,
+               android_LogPriority priority = ANDROID_LOG_DEBUG,
+               const char* prefix = 0,
+               bool ignoreBlankLines = false);
+
+    // Print the specified line to logcat. No \n at the end is necessary.
+    virtual void printLine(const char* string);
+
+private:
+    void printRaw(const char* string);
+
+    const char* mLogTag;
+    android_LogPriority mPriority;
+    const char* mPrefix;
+    bool mIgnoreBlankLines;
+}; // class LogPrinter
+
+// Print to a file descriptor
+class FdPrinter : public Printer {
+public:
+    // Create a printer using the specified file descriptor.
+    // - Each line will be prefixed with 'indent' number of blank spaces.
+    // - In addition, each line will be prefixed with the 'prefix' string.
+    FdPrinter(int fd, unsigned int indent = 0, const char* prefix = 0);
+
+    // Print the specified line to the file descriptor. \n is appended automatically.
+    virtual void printLine(const char* string);
+
+private:
+    enum {
+        MAX_FORMAT_STRING = 20,
+    };
+
+    int mFd;
+    unsigned int mIndent;
+    const char* mPrefix;
+    char mFormatString[MAX_FORMAT_STRING];
+}; // class FdPrinter
+
+class String8;
+
+// Print to a String8
+class String8Printer : public Printer {
+public:
+    // Create a printer using the specified String8 as the target.
+    // - In addition, each line will be prefixed with the 'prefix' string.
+    // - target's memory lifetime must be a superset of this String8Printer.
+    String8Printer(String8* target, const char* prefix = 0);
+
+    // Append the specified line to the String8. \n is appended automatically.
+    virtual void printLine(const char* string);
+
+private:
+    String8* mTarget;
+    const char* mPrefix;
+}; // class String8Printer
+
+// Print to an existing Printer by adding a prefix to each line
+class PrefixPrinter : public Printer {
+public:
+    // Create a printer using the specified printer as the target.
+    PrefixPrinter(Printer& printer, const char* prefix);
+
+    // Print the line (prefixed with prefix) using the printer.
+    virtual void printLine(const char* string);
+
+private:
+    Printer& mPrinter;
+    const char* mPrefix;
+};
+
+}; // namespace android
+
+#endif // ANDROID_PRINTER_H
diff --git a/package/utils/adbd/src/include/utils/ProcessCallStack.h b/package/utils/adbd/src/include/utils/ProcessCallStack.h
new file mode 100644
index 0000000..32458b8
--- /dev/null
+++ b/package/utils/adbd/src/include/utils/ProcessCallStack.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2013 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 ANDROID_PROCESS_CALLSTACK_H
+#define ANDROID_PROCESS_CALLSTACK_H
+
+#include <utils/CallStack.h>
+#include <android/log.h>
+#include <utils/KeyedVector.h>
+#include <utils/String8.h>
+
+#include <time.h>
+#include <sys/types.h>
+
+namespace android {
+
+class Printer;
+
+// Collect/print the call stack (function, file, line) traces for all threads in a process.
+class ProcessCallStack {
+public:
+    // Create an empty call stack. No-op.
+    ProcessCallStack();
+    // Copy the existing process callstack (no other side effects).
+    ProcessCallStack(const ProcessCallStack& rhs);
+    ~ProcessCallStack();
+
+    // Immediately collect the stack traces for all threads.
+    void update();
+
+    // Print all stack traces to the log using the supplied logtag.
+    void log(const char* logtag, android_LogPriority priority = ANDROID_LOG_DEBUG,
+             const char* prefix = 0) const;
+
+    // Dump all stack traces to the specified file descriptor.
+    void dump(int fd, int indent = 0, const char* prefix = 0) const;
+
+    // Return a string (possibly very long) containing all the stack traces.
+    String8 toString(const char* prefix = 0) const;
+
+    // Dump a serialized representation of all the stack traces to the specified printer.
+    void print(Printer& printer) const;
+
+    // Get the number of threads whose stack traces were collected.
+    size_t size() const;
+
+private:
+    void printInternal(Printer& printer, Printer& csPrinter) const;
+
+    // Reset the process's stack frames and metadata.
+    void clear();
+
+    struct ThreadInfo {
+        CallStack callStack;
+        String8 threadName;
+    };
+
+    // tid -> ThreadInfo
+    KeyedVector<pid_t, ThreadInfo> mThreadMap;
+    // Time that update() was last called
+    struct tm mTimeUpdated;
+};
+
+}; // namespace android
+
+#endif // ANDROID_PROCESS_CALLSTACK_H
diff --git a/package/utils/adbd/src/include/utils/PropertyMap.h b/package/utils/adbd/src/include/utils/PropertyMap.h
new file mode 100644
index 0000000..a9e674f
--- /dev/null
+++ b/package/utils/adbd/src/include/utils/PropertyMap.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2010 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 _UTILS_PROPERTY_MAP_H
+#define _UTILS_PROPERTY_MAP_H
+
+#include <utils/KeyedVector.h>
+#include <utils/String8.h>
+#include <utils/Errors.h>
+#include <utils/Tokenizer.h>
+
+namespace android {
+
+/*
+ * Provides a mechanism for passing around string-based property key / value pairs
+ * and loading them from property files.
+ *
+ * The property files have the following simple structure:
+ *
+ * # Comment
+ * key = value
+ *
+ * Keys and values are any sequence of printable ASCII characters.
+ * The '=' separates the key from the value.
+ * The key and value may not contain whitespace.
+ *
+ * The '\' character is reserved for escape sequences and is not currently supported.
+ * The '"" character is reserved for quoting and is not currently supported.
+ * Files that contain the '\' or '"' character will fail to parse.
+ *
+ * The file must not contain duplicate keys.
+ *
+ * TODO Support escape sequences and quoted values when needed.
+ */
+class PropertyMap {
+public:
+    /* Creates an empty property map. */
+    PropertyMap();
+    ~PropertyMap();
+
+    /* Clears the property map. */
+    void clear();
+
+    /* Adds a property.
+     * Replaces the property with the same key if it is already present.
+     */
+    void addProperty(const String8& key, const String8& value);
+
+    /* Returns true if the property map contains the specified key. */
+    bool hasProperty(const String8& key) const;
+
+    /* Gets the value of a property and parses it.
+     * Returns true and sets outValue if the key was found and its value was parsed successfully.
+     * Otherwise returns false and does not modify outValue.  (Also logs a warning.)
+     */
+    bool tryGetProperty(const String8& key, String8& outValue) const;
+    bool tryGetProperty(const String8& key, bool& outValue) const;
+    bool tryGetProperty(const String8& key, int32_t& outValue) const;
+    bool tryGetProperty(const String8& key, float& outValue) const;
+
+    /* Adds all values from the specified property map. */
+    void addAll(const PropertyMap* map);
+
+    /* Gets the underlying property map. */
+    inline const KeyedVector<String8, String8>& getProperties() const { return mProperties; }
+
+    /* Loads a property map from a file. */
+    static status_t load(const String8& filename, PropertyMap** outMap);
+
+private:
+    class Parser {
+        PropertyMap* mMap;
+        Tokenizer* mTokenizer;
+
+    public:
+        Parser(PropertyMap* map, Tokenizer* tokenizer);
+        ~Parser();
+        status_t parse();
+
+    private:
+        status_t parseType();
+        status_t parseKey();
+        status_t parseKeyProperty();
+        status_t parseModifier(const String8& token, int32_t* outMetaState);
+        status_t parseCharacterLiteral(char16_t* outCharacter);
+    };
+
+    KeyedVector<String8, String8> mProperties;
+};
+
+} // namespace android
+
+#endif // _UTILS_PROPERTY_MAP_H
diff --git a/package/utils/adbd/src/include/utils/RWLock.h b/package/utils/adbd/src/include/utils/RWLock.h
new file mode 100644
index 0000000..90beb5f
--- /dev/null
+++ b/package/utils/adbd/src/include/utils/RWLock.h
@@ -0,0 +1,126 @@
+/*
+ * 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 _LIBS_UTILS_RWLOCK_H
+#define _LIBS_UTILS_RWLOCK_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#if defined(HAVE_PTHREADS)
+# include <pthread.h>
+#endif
+
+#include <utils/Errors.h>
+#include <utils/ThreadDefs.h>
+
+// ---------------------------------------------------------------------------
+namespace android {
+// ---------------------------------------------------------------------------
+
+#if defined(HAVE_PTHREADS)
+
+/*
+ * Simple mutex class.  The implementation is system-dependent.
+ *
+ * The mutex must be unlocked by the thread that locked it.  They are not
+ * recursive, i.e. the same thread can't lock it multiple times.
+ */
+class RWLock {
+public:
+    enum {
+        PRIVATE = 0,
+        SHARED = 1
+    };
+
+                RWLock();
+                RWLock(const char* name);
+                RWLock(int type, const char* name = NULL);
+                ~RWLock();
+
+    status_t    readLock();
+    status_t    tryReadLock();
+    status_t    writeLock();
+    status_t    tryWriteLock();
+    void        unlock();
+
+    class AutoRLock {
+    public:
+        inline AutoRLock(RWLock& rwlock) : mLock(rwlock)  { mLock.readLock(); }
+        inline ~AutoRLock() { mLock.unlock(); }
+    private:
+        RWLock& mLock;
+    };
+
+    class AutoWLock {
+    public:
+        inline AutoWLock(RWLock& rwlock) : mLock(rwlock)  { mLock.writeLock(); }
+        inline ~AutoWLock() { mLock.unlock(); }
+    private:
+        RWLock& mLock;
+    };
+
+private:
+    // A RWLock cannot be copied
+                RWLock(const RWLock&);
+   RWLock&      operator = (const RWLock&);
+
+   pthread_rwlock_t mRWLock;
+};
+
+inline RWLock::RWLock() {
+    pthread_rwlock_init(&mRWLock, NULL);
+}
+inline RWLock::RWLock(__attribute__((unused)) const char* name) {
+    pthread_rwlock_init(&mRWLock, NULL);
+}
+inline RWLock::RWLock(int type, __attribute__((unused)) const char* name) {
+    if (type == SHARED) {
+        pthread_rwlockattr_t attr;
+        pthread_rwlockattr_init(&attr);
+        pthread_rwlockattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
+        pthread_rwlock_init(&mRWLock, &attr);
+        pthread_rwlockattr_destroy(&attr);
+    } else {
+        pthread_rwlock_init(&mRWLock, NULL);
+    }
+}
+inline RWLock::~RWLock() {
+    pthread_rwlock_destroy(&mRWLock);
+}
+inline status_t RWLock::readLock() {
+    return -pthread_rwlock_rdlock(&mRWLock);
+}
+inline status_t RWLock::tryReadLock() {
+    return -pthread_rwlock_tryrdlock(&mRWLock);
+}
+inline status_t RWLock::writeLock() {
+    return -pthread_rwlock_wrlock(&mRWLock);
+}
+inline status_t RWLock::tryWriteLock() {
+    return -pthread_rwlock_trywrlock(&mRWLock);
+}
+inline void RWLock::unlock() {
+    pthread_rwlock_unlock(&mRWLock);
+}
+
+#endif // HAVE_PTHREADS
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+// ---------------------------------------------------------------------------
+
+#endif // _LIBS_UTILS_RWLOCK_H
diff --git a/package/utils/adbd/src/include/utils/RefBase.h b/package/utils/adbd/src/include/utils/RefBase.h
new file mode 100644
index 0000000..8e15c19
--- /dev/null
+++ b/package/utils/adbd/src/include/utils/RefBase.h
@@ -0,0 +1,553 @@
+/*
+ * Copyright (C) 2005 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 ANDROID_REF_BASE_H
+#define ANDROID_REF_BASE_H
+
+#include <cutils/atomic.h>
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <utils/StrongPointer.h>
+#include <utils/TypeHelpers.h>
+
+// ---------------------------------------------------------------------------
+namespace android {
+
+class TextOutput;
+TextOutput& printWeakPointer(TextOutput& to, const void* val);
+
+// ---------------------------------------------------------------------------
+
+#define COMPARE_WEAK(_op_)                                      \
+inline bool operator _op_ (const sp<T>& o) const {              \
+    return m_ptr _op_ o.m_ptr;                                  \
+}                                                               \
+inline bool operator _op_ (const T* o) const {                  \
+    return m_ptr _op_ o;                                        \
+}                                                               \
+template<typename U>                                            \
+inline bool operator _op_ (const sp<U>& o) const {              \
+    return m_ptr _op_ o.m_ptr;                                  \
+}                                                               \
+template<typename U>                                            \
+inline bool operator _op_ (const U* o) const {                  \
+    return m_ptr _op_ o;                                        \
+}
+
+// ---------------------------------------------------------------------------
+
+class ReferenceRenamer {
+protected:
+    // destructor is purposedly not virtual so we avoid code overhead from
+    // subclasses; we have to make it protected to guarantee that it
+    // cannot be called from this base class (and to make strict compilers
+    // happy).
+    ~ReferenceRenamer() { }
+public:
+    virtual void operator()(size_t i) const = 0;
+};
+
+// ---------------------------------------------------------------------------
+
+class RefBase
+{
+public:
+            void            incStrong(const void* id) const;
+            void            decStrong(const void* id) const;
+    
+            void            forceIncStrong(const void* id) const;
+
+            //! DEBUGGING ONLY: Get current strong ref count.
+            int32_t         getStrongCount() const;
+
+    class weakref_type
+    {
+    public:
+        RefBase*            refBase() const;
+        
+        void                incWeak(const void* id);
+        void                decWeak(const void* id);
+        
+        // acquires a strong reference if there is already one.
+        bool                attemptIncStrong(const void* id);
+        
+        // acquires a weak reference if there is already one.
+        // This is not always safe. see ProcessState.cpp and BpBinder.cpp
+        // for proper use.
+        bool                attemptIncWeak(const void* id);
+
+        //! DEBUGGING ONLY: Get current weak ref count.
+        int32_t             getWeakCount() const;
+
+        //! DEBUGGING ONLY: Print references held on object.
+        void                printRefs() const;
+
+        //! DEBUGGING ONLY: Enable tracking for this object.
+        // enable -- enable/disable tracking
+        // retain -- when tracking is enable, if true, then we save a stack trace
+        //           for each reference and dereference; when retain == false, we
+        //           match up references and dereferences and keep only the 
+        //           outstanding ones.
+        
+        void                trackMe(bool enable, bool retain);
+    };
+    
+            weakref_type*   createWeak(const void* id) const;
+            
+            weakref_type*   getWeakRefs() const;
+
+            //! DEBUGGING ONLY: Print references held on object.
+    inline  void            printRefs() const { getWeakRefs()->printRefs(); }
+
+            //! DEBUGGING ONLY: Enable tracking of object.
+    inline  void            trackMe(bool enable, bool retain)
+    { 
+        getWeakRefs()->trackMe(enable, retain); 
+    }
+
+    typedef RefBase basetype;
+
+protected:
+                            RefBase();
+    virtual                 ~RefBase();
+    
+    //! Flags for extendObjectLifetime()
+    enum {
+        OBJECT_LIFETIME_STRONG  = 0x0000,
+        OBJECT_LIFETIME_WEAK    = 0x0001,
+        OBJECT_LIFETIME_MASK    = 0x0001
+    };
+    
+            void            extendObjectLifetime(int32_t mode);
+            
+    //! Flags for onIncStrongAttempted()
+    enum {
+        FIRST_INC_STRONG = 0x0001
+    };
+    
+    virtual void            onFirstRef();
+    virtual void            onLastStrongRef(const void* id);
+    virtual bool            onIncStrongAttempted(uint32_t flags, const void* id);
+    virtual void            onLastWeakRef(const void* id);
+
+private:
+    friend class weakref_type;
+    class weakref_impl;
+    
+                            RefBase(const RefBase& o);
+            RefBase&        operator=(const RefBase& o);
+
+private:
+    friend class ReferenceMover;
+
+    static void renameRefs(size_t n, const ReferenceRenamer& renamer);
+
+    static void renameRefId(weakref_type* ref,
+            const void* old_id, const void* new_id);
+
+    static void renameRefId(RefBase* ref,
+            const void* old_id, const void* new_id);
+
+        weakref_impl* const mRefs;
+};
+
+// ---------------------------------------------------------------------------
+
+template <class T>
+class LightRefBase
+{
+public:
+    inline LightRefBase() : mCount(0) { }
+    inline void incStrong(__attribute__((unused)) const void* id) const {
+        android_atomic_inc(&mCount);
+    }
+    inline void decStrong(__attribute__((unused)) const void* id) const {
+        if (android_atomic_dec(&mCount) == 1) {
+            delete static_cast<const T*>(this);
+        }
+    }
+    //! DEBUGGING ONLY: Get current strong ref count.
+    inline int32_t getStrongCount() const {
+        return mCount;
+    }
+
+    typedef LightRefBase<T> basetype;
+
+protected:
+    inline ~LightRefBase() { }
+
+private:
+    friend class ReferenceMover;
+    inline static void renameRefs(size_t n, const ReferenceRenamer& renamer) { }
+    inline static void renameRefId(T* ref,
+            const void* old_id, const void* new_id) { }
+
+private:
+    mutable volatile int32_t mCount;
+};
+
+// This is a wrapper around LightRefBase that simply enforces a virtual
+// destructor to eliminate the template requirement of LightRefBase
+class VirtualLightRefBase : public LightRefBase<VirtualLightRefBase> {
+public:
+    virtual ~VirtualLightRefBase() {}
+};
+
+// ---------------------------------------------------------------------------
+
+template <typename T>
+class wp
+{
+public:
+    typedef typename RefBase::weakref_type weakref_type;
+    
+    inline wp() : m_ptr(0) { }
+
+    wp(T* other);
+    wp(const wp<T>& other);
+    wp(const sp<T>& other);
+    template<typename U> wp(U* other);
+    template<typename U> wp(const sp<U>& other);
+    template<typename U> wp(const wp<U>& other);
+
+    ~wp();
+    
+    // Assignment
+
+    wp& operator = (T* other);
+    wp& operator = (const wp<T>& other);
+    wp& operator = (const sp<T>& other);
+    
+    template<typename U> wp& operator = (U* other);
+    template<typename U> wp& operator = (const wp<U>& other);
+    template<typename U> wp& operator = (const sp<U>& other);
+    
+    void set_object_and_refs(T* other, weakref_type* refs);
+
+    // promotion to sp
+    
+    sp<T> promote() const;
+
+    // Reset
+    
+    void clear();
+
+    // Accessors
+    
+    inline  weakref_type* get_refs() const { return m_refs; }
+    
+    inline  T* unsafe_get() const { return m_ptr; }
+
+    // Operators
+
+    COMPARE_WEAK(==)
+    COMPARE_WEAK(!=)
+    COMPARE_WEAK(>)
+    COMPARE_WEAK(<)
+    COMPARE_WEAK(<=)
+    COMPARE_WEAK(>=)
+
+    inline bool operator == (const wp<T>& o) const {
+        return (m_ptr == o.m_ptr) && (m_refs == o.m_refs);
+    }
+    template<typename U>
+    inline bool operator == (const wp<U>& o) const {
+        return m_ptr == o.m_ptr;
+    }
+
+    inline bool operator > (const wp<T>& o) const {
+        return (m_ptr == o.m_ptr) ? (m_refs > o.m_refs) : (m_ptr > o.m_ptr);
+    }
+    template<typename U>
+    inline bool operator > (const wp<U>& o) const {
+        return (m_ptr == o.m_ptr) ? (m_refs > o.m_refs) : (m_ptr > o.m_ptr);
+    }
+
+    inline bool operator < (const wp<T>& o) const {
+        return (m_ptr == o.m_ptr) ? (m_refs < o.m_refs) : (m_ptr < o.m_ptr);
+    }
+    template<typename U>
+    inline bool operator < (const wp<U>& o) const {
+        return (m_ptr == o.m_ptr) ? (m_refs < o.m_refs) : (m_ptr < o.m_ptr);
+    }
+                         inline bool operator != (const wp<T>& o) const { return m_refs != o.m_refs; }
+    template<typename U> inline bool operator != (const wp<U>& o) const { return !operator == (o); }
+                         inline bool operator <= (const wp<T>& o) const { return !operator > (o); }
+    template<typename U> inline bool operator <= (const wp<U>& o) const { return !operator > (o); }
+                         inline bool operator >= (const wp<T>& o) const { return !operator < (o); }
+    template<typename U> inline bool operator >= (const wp<U>& o) const { return !operator < (o); }
+
+private:
+    template<typename Y> friend class sp;
+    template<typename Y> friend class wp;
+
+    T*              m_ptr;
+    weakref_type*   m_refs;
+};
+
+template <typename T>
+TextOutput& operator<<(TextOutput& to, const wp<T>& val);
+
+#undef COMPARE_WEAK
+
+// ---------------------------------------------------------------------------
+// No user serviceable parts below here.
+
+template<typename T>
+wp<T>::wp(T* other)
+    : m_ptr(other)
+{
+    if (other) m_refs = other->createWeak(this);
+}
+
+template<typename T>
+wp<T>::wp(const wp<T>& other)
+    : m_ptr(other.m_ptr), m_refs(other.m_refs)
+{
+    if (m_ptr) m_refs->incWeak(this);
+}
+
+template<typename T>
+wp<T>::wp(const sp<T>& other)
+    : m_ptr(other.m_ptr)
+{
+    if (m_ptr) {
+        m_refs = m_ptr->createWeak(this);
+    }
+}
+
+template<typename T> template<typename U>
+wp<T>::wp(U* other)
+    : m_ptr(other)
+{
+    if (other) m_refs = other->createWeak(this);
+}
+
+template<typename T> template<typename U>
+wp<T>::wp(const wp<U>& other)
+    : m_ptr(other.m_ptr)
+{
+    if (m_ptr) {
+        m_refs = other.m_refs;
+        m_refs->incWeak(this);
+    }
+}
+
+template<typename T> template<typename U>
+wp<T>::wp(const sp<U>& other)
+    : m_ptr(other.m_ptr)
+{
+    if (m_ptr) {
+        m_refs = m_ptr->createWeak(this);
+    }
+}
+
+template<typename T>
+wp<T>::~wp()
+{
+    if (m_ptr) m_refs->decWeak(this);
+}
+
+template<typename T>
+wp<T>& wp<T>::operator = (T* other)
+{
+    weakref_type* newRefs =
+        other ? other->createWeak(this) : 0;
+    if (m_ptr) m_refs->decWeak(this);
+    m_ptr = other;
+    m_refs = newRefs;
+    return *this;
+}
+
+template<typename T>
+wp<T>& wp<T>::operator = (const wp<T>& other)
+{
+    weakref_type* otherRefs(other.m_refs);
+    T* otherPtr(other.m_ptr);
+    if (otherPtr) otherRefs->incWeak(this);
+    if (m_ptr) m_refs->decWeak(this);
+    m_ptr = otherPtr;
+    m_refs = otherRefs;
+    return *this;
+}
+
+template<typename T>
+wp<T>& wp<T>::operator = (const sp<T>& other)
+{
+    weakref_type* newRefs =
+        other != NULL ? other->createWeak(this) : 0;
+    T* otherPtr(other.m_ptr);
+    if (m_ptr) m_refs->decWeak(this);
+    m_ptr = otherPtr;
+    m_refs = newRefs;
+    return *this;
+}
+
+template<typename T> template<typename U>
+wp<T>& wp<T>::operator = (U* other)
+{
+    weakref_type* newRefs =
+        other ? other->createWeak(this) : 0;
+    if (m_ptr) m_refs->decWeak(this);
+    m_ptr = other;
+    m_refs = newRefs;
+    return *this;
+}
+
+template<typename T> template<typename U>
+wp<T>& wp<T>::operator = (const wp<U>& other)
+{
+    weakref_type* otherRefs(other.m_refs);
+    U* otherPtr(other.m_ptr);
+    if (otherPtr) otherRefs->incWeak(this);
+    if (m_ptr) m_refs->decWeak(this);
+    m_ptr = otherPtr;
+    m_refs = otherRefs;
+    return *this;
+}
+
+template<typename T> template<typename U>
+wp<T>& wp<T>::operator = (const sp<U>& other)
+{
+    weakref_type* newRefs =
+        other != NULL ? other->createWeak(this) : 0;
+    U* otherPtr(other.m_ptr);
+    if (m_ptr) m_refs->decWeak(this);
+    m_ptr = otherPtr;
+    m_refs = newRefs;
+    return *this;
+}
+
+template<typename T>
+void wp<T>::set_object_and_refs(T* other, weakref_type* refs)
+{
+    if (other) refs->incWeak(this);
+    if (m_ptr) m_refs->decWeak(this);
+    m_ptr = other;
+    m_refs = refs;
+}
+
+template<typename T>
+sp<T> wp<T>::promote() const
+{
+    sp<T> result;
+    if (m_ptr && m_refs->attemptIncStrong(&result)) {
+        result.set_pointer(m_ptr);
+    }
+    return result;
+}
+
+template<typename T>
+void wp<T>::clear()
+{
+    if (m_ptr) {
+        m_refs->decWeak(this);
+        m_ptr = 0;
+    }
+}
+
+template <typename T>
+inline TextOutput& operator<<(TextOutput& to, const wp<T>& val)
+{
+    return printWeakPointer(to, val.unsafe_get());
+}
+
+// ---------------------------------------------------------------------------
+
+// this class just serves as a namespace so TYPE::moveReferences can stay
+// private.
+class ReferenceMover {
+public:
+    // it would be nice if we could make sure no extra code is generated
+    // for sp<TYPE> or wp<TYPE> when TYPE is a descendant of RefBase:
+    // Using a sp<RefBase> override doesn't work; it's a bit like we wanted
+    // a template<typename TYPE inherits RefBase> template...
+
+    template<typename TYPE> static inline
+    void move_references(sp<TYPE>* d, sp<TYPE> const* s, size_t n) {
+
+        class Renamer : public ReferenceRenamer {
+            sp<TYPE>* d;
+            sp<TYPE> const* s;
+            virtual void operator()(size_t i) const {
+                // The id are known to be the sp<>'s this pointer
+                TYPE::renameRefId(d[i].get(), &s[i], &d[i]);
+            }
+        public:
+            Renamer(sp<TYPE>* d, sp<TYPE> const* s) : s(s), d(d) { }
+        };
+
+        memmove(d, s, n*sizeof(sp<TYPE>));
+        TYPE::renameRefs(n, Renamer(d, s));
+    }
+
+
+    template<typename TYPE> static inline
+    void move_references(wp<TYPE>* d, wp<TYPE> const* s, size_t n) {
+
+        class Renamer : public ReferenceRenamer {
+            wp<TYPE>* d;
+            wp<TYPE> const* s;
+            virtual void operator()(size_t i) const {
+                // The id are known to be the wp<>'s this pointer
+                TYPE::renameRefId(d[i].get_refs(), &s[i], &d[i]);
+            }
+        public:
+            Renamer(wp<TYPE>* d, wp<TYPE> const* s) : s(s), d(d) { }
+        };
+
+        memmove(d, s, n*sizeof(wp<TYPE>));
+        TYPE::renameRefs(n, Renamer(d, s));
+    }
+};
+
+// specialization for moving sp<> and wp<> types.
+// these are used by the [Sorted|Keyed]Vector<> implementations
+// sp<> and wp<> need to be handled specially, because they do not
+// have trivial copy operation in the general case (see RefBase.cpp
+// when DEBUG ops are enabled), but can be implemented very
+// efficiently in most cases.
+
+template<typename TYPE> inline
+void move_forward_type(sp<TYPE>* d, sp<TYPE> const* s, size_t n) {
+    ReferenceMover::move_references(d, s, n);
+}
+
+template<typename TYPE> inline
+void move_backward_type(sp<TYPE>* d, sp<TYPE> const* s, size_t n) {
+    ReferenceMover::move_references(d, s, n);
+}
+
+template<typename TYPE> inline
+void move_forward_type(wp<TYPE>* d, wp<TYPE> const* s, size_t n) {
+    ReferenceMover::move_references(d, s, n);
+}
+
+template<typename TYPE> inline
+void move_backward_type(wp<TYPE>* d, wp<TYPE> const* s, size_t n) {
+    ReferenceMover::move_references(d, s, n);
+}
+
+
+}; // namespace android
+
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_REF_BASE_H
diff --git a/package/utils/adbd/src/include/utils/SharedBuffer.h b/package/utils/adbd/src/include/utils/SharedBuffer.h
new file mode 100644
index 0000000..b670953
--- /dev/null
+++ b/package/utils/adbd/src/include/utils/SharedBuffer.h
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2005 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 ANDROID_SHARED_BUFFER_H
+#define ANDROID_SHARED_BUFFER_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+// ---------------------------------------------------------------------------
+
+namespace android {
+
+class SharedBuffer
+{
+public:
+
+    /* flags to use with release() */
+    enum {
+        eKeepStorage = 0x00000001
+    };
+
+    /*! allocate a buffer of size 'size' and acquire() it.
+     *  call release() to free it.
+     */
+    static          SharedBuffer*           alloc(size_t size);
+    
+    /*! free the memory associated with the SharedBuffer.
+     * Fails if there are any users associated with this SharedBuffer.
+     * In other words, the buffer must have been release by all its
+     * users.
+     */
+    static          ssize_t                 dealloc(const SharedBuffer* released);
+
+    //! access the data for read
+    inline          const void*             data() const;
+    
+    //! access the data for read/write
+    inline          void*                   data();
+
+    //! get size of the buffer
+    inline          size_t                  size() const;
+ 
+    //! get back a SharedBuffer object from its data
+    static  inline  SharedBuffer*           bufferFromData(void* data);
+    
+    //! get back a SharedBuffer object from its data
+    static  inline  const SharedBuffer*     bufferFromData(const void* data);
+
+    //! get the size of a SharedBuffer object from its data
+    static  inline  size_t                  sizeFromData(const void* data);
+    
+    //! edit the buffer (get a writtable, or non-const, version of it)
+                    SharedBuffer*           edit() const;
+
+    //! edit the buffer, resizing if needed
+                    SharedBuffer*           editResize(size_t size) const;
+
+    //! like edit() but fails if a copy is required
+                    SharedBuffer*           attemptEdit() const;
+    
+    //! resize and edit the buffer, loose it's content.
+                    SharedBuffer*           reset(size_t size) const;
+
+    //! acquire/release a reference on this buffer
+                    void                    acquire() const;
+                    
+    /*! release a reference on this buffer, with the option of not
+     * freeing the memory associated with it if it was the last reference
+     * returns the previous reference count
+     */     
+                    int32_t                 release(uint32_t flags = 0) const;
+    
+    //! returns wether or not we're the only owner
+    inline          bool                    onlyOwner() const;
+    
+
+private:
+        inline SharedBuffer() { }
+        inline ~SharedBuffer() { }
+        SharedBuffer(const SharedBuffer&);
+        SharedBuffer& operator = (const SharedBuffer&);
+ 
+        // 16 bytes. must be sized to preserve correct alignment.
+        mutable int32_t        mRefs;
+                size_t         mSize;
+                uint32_t       mReserved[2];
+};
+
+// ---------------------------------------------------------------------------
+
+const void* SharedBuffer::data() const {
+    return this + 1;
+}
+
+void* SharedBuffer::data() {
+    return this + 1;
+}
+
+size_t SharedBuffer::size() const {
+    return mSize;
+}
+
+SharedBuffer* SharedBuffer::bufferFromData(void* data) {
+    return data ? static_cast<SharedBuffer *>(data)-1 : 0;
+}
+    
+const SharedBuffer* SharedBuffer::bufferFromData(const void* data) {
+    return data ? static_cast<const SharedBuffer *>(data)-1 : 0;
+}
+
+size_t SharedBuffer::sizeFromData(const void* data) {
+    return data ? bufferFromData(data)->mSize : 0;
+}
+
+bool SharedBuffer::onlyOwner() const {
+    return (mRefs == 1);
+}
+
+}; // namespace android
+
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_VECTOR_H
diff --git a/package/utils/adbd/src/include/utils/Singleton.h b/package/utils/adbd/src/include/utils/Singleton.h
new file mode 100644
index 0000000..c60680e
--- /dev/null
+++ b/package/utils/adbd/src/include/utils/Singleton.h
@@ -0,0 +1,77 @@
+/*
+ * 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 ANDROID_UTILS_SINGLETON_H
+#define ANDROID_UTILS_SINGLETON_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <utils/threads.h>
+#include <cutils/compiler.h>
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+template <typename TYPE>
+class ANDROID_API Singleton
+{
+public:
+    static TYPE& getInstance() {
+        Mutex::Autolock _l(sLock);
+        TYPE* instance = sInstance;
+        if (instance == 0) {
+            instance = new TYPE();
+            sInstance = instance;
+        }
+        return *instance;
+    }
+
+    static bool hasInstance() {
+        Mutex::Autolock _l(sLock);
+        return sInstance != 0;
+    }
+    
+protected:
+    ~Singleton() { };
+    Singleton() { };
+
+private:
+    Singleton(const Singleton&);
+    Singleton& operator = (const Singleton&);
+    static Mutex sLock;
+    static TYPE* sInstance;
+};
+
+/*
+ * use ANDROID_SINGLETON_STATIC_INSTANCE(TYPE) in your implementation file
+ * (eg: <TYPE>.cpp) to create the static instance of Singleton<>'s attributes,
+ * and avoid to have a copy of them in each compilation units Singleton<TYPE>
+ * is used.
+ * NOTE: we use a version of Mutex ctor that takes a parameter, because
+ * for some unknown reason using the default ctor doesn't emit the variable!
+ */
+
+#define ANDROID_SINGLETON_STATIC_INSTANCE(TYPE)                 \
+    template<> Mutex Singleton< TYPE >::sLock(Mutex::PRIVATE);  \
+    template<> TYPE* Singleton< TYPE >::sInstance(0);           \
+    template class Singleton< TYPE >;
+
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_UTILS_SINGLETON_H
+
diff --git a/package/utils/adbd/src/include/utils/SortedVector.h b/package/utils/adbd/src/include/utils/SortedVector.h
new file mode 100644
index 0000000..2d3e82a
--- /dev/null
+++ b/package/utils/adbd/src/include/utils/SortedVector.h
@@ -0,0 +1,282 @@
+/*
+ * Copyright (C) 2005 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 ANDROID_SORTED_VECTOR_H
+#define ANDROID_SORTED_VECTOR_H
+
+#include <assert.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <cutils/log.h>
+
+#include <utils/Vector.h>
+#include <utils/VectorImpl.h>
+#include <utils/TypeHelpers.h>
+
+// ---------------------------------------------------------------------------
+
+namespace android {
+
+template <class TYPE>
+class SortedVector : private SortedVectorImpl
+{
+    friend class Vector<TYPE>;
+
+public:
+            typedef TYPE    value_type;
+    
+    /*! 
+     * Constructors and destructors
+     */
+    
+                            SortedVector();
+                            SortedVector(const SortedVector<TYPE>& rhs);
+    virtual                 ~SortedVector();
+
+    /*! copy operator */
+    const SortedVector<TYPE>&   operator = (const SortedVector<TYPE>& rhs) const;    
+    SortedVector<TYPE>&         operator = (const SortedVector<TYPE>& rhs);    
+
+    /*
+     * empty the vector
+     */
+
+    inline  void            clear()             { VectorImpl::clear(); }
+
+    /*! 
+     * vector stats
+     */
+
+    //! returns number of items in the vector
+    inline  size_t          size() const                { return VectorImpl::size(); }
+    //! returns whether or not the vector is empty
+    inline  bool            isEmpty() const             { return VectorImpl::isEmpty(); }
+    //! returns how many items can be stored without reallocating the backing store
+    inline  size_t          capacity() const            { return VectorImpl::capacity(); }
+    //! sets the capacity. capacity can never be reduced less than size()
+    inline  ssize_t         setCapacity(size_t size)    { return VectorImpl::setCapacity(size); }
+
+    /*! 
+     * C-style array access
+     */
+     
+    //! read-only C-style access 
+    inline  const TYPE*     array() const;
+
+    //! read-write C-style access. BE VERY CAREFUL when modifying the array
+    //! you must keep it sorted! You usually don't use this function.
+            TYPE*           editArray();
+
+            //! finds the index of an item
+            ssize_t         indexOf(const TYPE& item) const;
+            
+            //! finds where this item should be inserted
+            size_t          orderOf(const TYPE& item) const;
+            
+    
+    /*! 
+     * accessors
+     */
+
+    //! read-only access to an item at a given index
+    inline  const TYPE&     operator [] (size_t index) const;
+    //! alternate name for operator []
+    inline  const TYPE&     itemAt(size_t index) const;
+    //! stack-usage of the vector. returns the top of the stack (last element)
+            const TYPE&     top() const;
+
+    /*!
+     * modifying the array
+     */
+
+            //! add an item in the right place (and replace the one that is there)
+            ssize_t         add(const TYPE& item);
+            
+            //! editItemAt() MUST NOT change the order of this item
+            TYPE&           editItemAt(size_t index) {
+                return *( static_cast<TYPE *>(VectorImpl::editItemLocation(index)) );
+            }
+
+            //! merges a vector into this one
+            ssize_t         merge(const Vector<TYPE>& vector);
+            ssize_t         merge(const SortedVector<TYPE>& vector);
+            
+            //! removes an item
+            ssize_t         remove(const TYPE&);
+
+    //! remove several items
+    inline  ssize_t         removeItemsAt(size_t index, size_t count = 1);
+    //! remove one item
+    inline  ssize_t         removeAt(size_t index)  { return removeItemsAt(index); }
+            
+protected:
+    virtual void    do_construct(void* storage, size_t num) const;
+    virtual void    do_destroy(void* storage, size_t num) const;
+    virtual void    do_copy(void* dest, const void* from, size_t num) const;
+    virtual void    do_splat(void* dest, const void* item, size_t num) const;
+    virtual void    do_move_forward(void* dest, const void* from, size_t num) const;
+    virtual void    do_move_backward(void* dest, const void* from, size_t num) const;
+    virtual int     do_compare(const void* lhs, const void* rhs) const;
+};
+
+// SortedVector<T> can be trivially moved using memcpy() because moving does not
+// require any change to the underlying SharedBuffer contents or reference count.
+template<typename T> struct trait_trivial_move<SortedVector<T> > { enum { value = true }; };
+
+// ---------------------------------------------------------------------------
+// No user serviceable parts from here...
+// ---------------------------------------------------------------------------
+
+template<class TYPE> inline
+SortedVector<TYPE>::SortedVector()
+    : SortedVectorImpl(sizeof(TYPE),
+                ((traits<TYPE>::has_trivial_ctor   ? HAS_TRIVIAL_CTOR   : 0)
+                |(traits<TYPE>::has_trivial_dtor   ? HAS_TRIVIAL_DTOR   : 0)
+                |(traits<TYPE>::has_trivial_copy   ? HAS_TRIVIAL_COPY   : 0))
+                )
+{
+}
+
+template<class TYPE> inline
+SortedVector<TYPE>::SortedVector(const SortedVector<TYPE>& rhs)
+    : SortedVectorImpl(rhs) {
+}
+
+template<class TYPE> inline
+SortedVector<TYPE>::~SortedVector() {
+    finish_vector();
+}
+
+template<class TYPE> inline
+SortedVector<TYPE>& SortedVector<TYPE>::operator = (const SortedVector<TYPE>& rhs) {
+    SortedVectorImpl::operator = (rhs);
+    return *this; 
+}
+
+template<class TYPE> inline
+const SortedVector<TYPE>& SortedVector<TYPE>::operator = (const SortedVector<TYPE>& rhs) const {
+    SortedVectorImpl::operator = (rhs);
+    return *this; 
+}
+
+template<class TYPE> inline
+const TYPE* SortedVector<TYPE>::array() const {
+    return static_cast<const TYPE *>(arrayImpl());
+}
+
+template<class TYPE> inline
+TYPE* SortedVector<TYPE>::editArray() {
+    return static_cast<TYPE *>(editArrayImpl());
+}
+
+
+template<class TYPE> inline
+const TYPE& SortedVector<TYPE>::operator[](size_t index) const {
+    LOG_FATAL_IF(index>=size(),
+            "%s: index=%u out of range (%u)", __PRETTY_FUNCTION__,
+            int(index), int(size()));
+    return *(array() + index);
+}
+
+template<class TYPE> inline
+const TYPE& SortedVector<TYPE>::itemAt(size_t index) const {
+    return operator[](index);
+}
+
+template<class TYPE> inline
+const TYPE& SortedVector<TYPE>::top() const {
+    return *(array() + size() - 1);
+}
+
+template<class TYPE> inline
+ssize_t SortedVector<TYPE>::add(const TYPE& item) {
+    return SortedVectorImpl::add(&item);
+}
+
+template<class TYPE> inline
+ssize_t SortedVector<TYPE>::indexOf(const TYPE& item) const {
+    return SortedVectorImpl::indexOf(&item);
+}
+
+template<class TYPE> inline
+size_t SortedVector<TYPE>::orderOf(const TYPE& item) const {
+    return SortedVectorImpl::orderOf(&item);
+}
+
+template<class TYPE> inline
+ssize_t SortedVector<TYPE>::merge(const Vector<TYPE>& vector) {
+    return SortedVectorImpl::merge(reinterpret_cast<const VectorImpl&>(vector));
+}
+
+template<class TYPE> inline
+ssize_t SortedVector<TYPE>::merge(const SortedVector<TYPE>& vector) {
+    return SortedVectorImpl::merge(reinterpret_cast<const SortedVectorImpl&>(vector));
+}
+
+template<class TYPE> inline
+ssize_t SortedVector<TYPE>::remove(const TYPE& item) {
+    return SortedVectorImpl::remove(&item);
+}
+
+template<class TYPE> inline
+ssize_t SortedVector<TYPE>::removeItemsAt(size_t index, size_t count) {
+    return VectorImpl::removeItemsAt(index, count);
+}
+
+// ---------------------------------------------------------------------------
+
+template<class TYPE>
+void SortedVector<TYPE>::do_construct(void* storage, size_t num) const {
+    construct_type( reinterpret_cast<TYPE*>(storage), num );
+}
+
+template<class TYPE>
+void SortedVector<TYPE>::do_destroy(void* storage, size_t num) const {
+    destroy_type( reinterpret_cast<TYPE*>(storage), num );
+}
+
+template<class TYPE>
+void SortedVector<TYPE>::do_copy(void* dest, const void* from, size_t num) const {
+    copy_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(from), num );
+}
+
+template<class TYPE>
+void SortedVector<TYPE>::do_splat(void* dest, const void* item, size_t num) const {
+    splat_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(item), num );
+}
+
+template<class TYPE>
+void SortedVector<TYPE>::do_move_forward(void* dest, const void* from, size_t num) const {
+    move_forward_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(from), num );
+}
+
+template<class TYPE>
+void SortedVector<TYPE>::do_move_backward(void* dest, const void* from, size_t num) const {
+    move_backward_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(from), num );
+}
+
+template<class TYPE>
+int SortedVector<TYPE>::do_compare(const void* lhs, const void* rhs) const {
+    return compare_type( *reinterpret_cast<const TYPE*>(lhs), *reinterpret_cast<const TYPE*>(rhs) );
+}
+
+}; // namespace android
+
+
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_SORTED_VECTOR_H
diff --git a/package/utils/adbd/src/include/utils/StopWatch.h b/package/utils/adbd/src/include/utils/StopWatch.h
new file mode 100644
index 0000000..693dd3c
--- /dev/null
+++ b/package/utils/adbd/src/include/utils/StopWatch.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2005 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 ANDROID_STOPWATCH_H
+#define ANDROID_STOPWATCH_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/Timers.h>
+
+// ---------------------------------------------------------------------------
+
+namespace android {
+
+class StopWatch
+{
+public:
+        StopWatch(  const char *name,
+                    int clock = SYSTEM_TIME_MONOTONIC,
+                    uint32_t flags = 0);
+        ~StopWatch();
+        
+        const char* name() const;
+        nsecs_t     lap();
+        nsecs_t     elapsedTime() const;
+
+        void        reset();
+        
+private:
+    const char*     mName;
+    int             mClock;
+    uint32_t        mFlags;
+    
+    struct lap_t {
+        nsecs_t     soFar;
+        nsecs_t     thisLap;
+    };
+    
+    nsecs_t         mStartTime;
+    lap_t           mLaps[8];
+    int             mNumLaps;
+};
+
+
+}; // namespace android
+
+
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_STOPWATCH_H
diff --git a/package/utils/adbd/src/include/utils/String16.h b/package/utils/adbd/src/include/utils/String16.h
new file mode 100644
index 0000000..d131bfc
--- /dev/null
+++ b/package/utils/adbd/src/include/utils/String16.h
@@ -0,0 +1,250 @@
+/*
+ * Copyright (C) 2005 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 ANDROID_STRING16_H
+#define ANDROID_STRING16_H
+
+#include <utils/Errors.h>
+#include <utils/SharedBuffer.h>
+#include <utils/Unicode.h>
+#include <utils/TypeHelpers.h>
+
+// ---------------------------------------------------------------------------
+
+extern "C" {
+
+}
+
+// ---------------------------------------------------------------------------
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+class String8;
+class TextOutput;
+
+//! This is a string holding UTF-16 characters.
+class String16
+{
+public:
+    /* use String16(StaticLinkage) if you're statically linking against
+     * libutils and declaring an empty static String16, e.g.:
+     *
+     *   static String16 sAStaticEmptyString(String16::kEmptyString);
+     *   static String16 sAnotherStaticEmptyString(sAStaticEmptyString);
+     */
+    enum StaticLinkage { kEmptyString };
+
+                                String16();
+    explicit                    String16(StaticLinkage);
+                                String16(const String16& o);
+                                String16(const String16& o,
+                                         size_t len,
+                                         size_t begin=0);
+    explicit                    String16(const char16_t* o);
+    explicit                    String16(const char16_t* o, size_t len);
+    explicit                    String16(const String8& o);
+    explicit                    String16(const char* o);
+    explicit                    String16(const char* o, size_t len);
+
+                                ~String16();
+    
+    inline  const char16_t*     string() const;
+    inline  size_t              size() const;
+    
+    inline  const SharedBuffer* sharedBuffer() const;
+    
+            void                setTo(const String16& other);
+            status_t            setTo(const char16_t* other);
+            status_t            setTo(const char16_t* other, size_t len);
+            status_t            setTo(const String16& other,
+                                      size_t len,
+                                      size_t begin=0);
+    
+            status_t            append(const String16& other);
+            status_t            append(const char16_t* other, size_t len);
+            
+    inline  String16&           operator=(const String16& other);
+    
+    inline  String16&           operator+=(const String16& other);
+    inline  String16            operator+(const String16& other) const;
+
+            status_t            insert(size_t pos, const char16_t* chrs);
+            status_t            insert(size_t pos,
+                                       const char16_t* chrs, size_t len);
+
+            ssize_t             findFirst(char16_t c) const;
+            ssize_t             findLast(char16_t c) const;
+
+            bool                startsWith(const String16& prefix) const;
+            bool                startsWith(const char16_t* prefix) const;
+            
+            status_t            makeLower();
+
+            status_t            replaceAll(char16_t replaceThis,
+                                           char16_t withThis);
+
+            status_t            remove(size_t len, size_t begin=0);
+
+    inline  int                 compare(const String16& other) const;
+
+    inline  bool                operator<(const String16& other) const;
+    inline  bool                operator<=(const String16& other) const;
+    inline  bool                operator==(const String16& other) const;
+    inline  bool                operator!=(const String16& other) const;
+    inline  bool                operator>=(const String16& other) const;
+    inline  bool                operator>(const String16& other) const;
+    
+    inline  bool                operator<(const char16_t* other) const;
+    inline  bool                operator<=(const char16_t* other) const;
+    inline  bool                operator==(const char16_t* other) const;
+    inline  bool                operator!=(const char16_t* other) const;
+    inline  bool                operator>=(const char16_t* other) const;
+    inline  bool                operator>(const char16_t* other) const;
+    
+    inline                      operator const char16_t*() const;
+    
+private:
+            const char16_t*     mString;
+};
+
+// String16 can be trivially moved using memcpy() because moving does not
+// require any change to the underlying SharedBuffer contents or reference count.
+ANDROID_TRIVIAL_MOVE_TRAIT(String16)
+
+// ---------------------------------------------------------------------------
+// No user servicable parts below.
+
+inline int compare_type(const String16& lhs, const String16& rhs)
+{
+    return lhs.compare(rhs);
+}
+
+inline int strictly_order_type(const String16& lhs, const String16& rhs)
+{
+    return compare_type(lhs, rhs) < 0;
+}
+
+inline const char16_t* String16::string() const
+{
+    return mString;
+}
+
+inline size_t String16::size() const
+{
+    return SharedBuffer::sizeFromData(mString)/sizeof(char16_t)-1;
+}
+
+inline const SharedBuffer* String16::sharedBuffer() const
+{
+    return SharedBuffer::bufferFromData(mString);
+}
+
+inline String16& String16::operator=(const String16& other)
+{
+    setTo(other);
+    return *this;
+}
+
+inline String16& String16::operator+=(const String16& other)
+{
+    append(other);
+    return *this;
+}
+
+inline String16 String16::operator+(const String16& other) const
+{
+    String16 tmp(*this);
+    tmp += other;
+    return tmp;
+}
+
+inline int String16::compare(const String16& other) const
+{
+    return strzcmp16(mString, size(), other.mString, other.size());
+}
+
+inline bool String16::operator<(const String16& other) const
+{
+    return strzcmp16(mString, size(), other.mString, other.size()) < 0;
+}
+
+inline bool String16::operator<=(const String16& other) const
+{
+    return strzcmp16(mString, size(), other.mString, other.size()) <= 0;
+}
+
+inline bool String16::operator==(const String16& other) const
+{
+    return strzcmp16(mString, size(), other.mString, other.size()) == 0;
+}
+
+inline bool String16::operator!=(const String16& other) const
+{
+    return strzcmp16(mString, size(), other.mString, other.size()) != 0;
+}
+
+inline bool String16::operator>=(const String16& other) const
+{
+    return strzcmp16(mString, size(), other.mString, other.size()) >= 0;
+}
+
+inline bool String16::operator>(const String16& other) const
+{
+    return strzcmp16(mString, size(), other.mString, other.size()) > 0;
+}
+
+inline bool String16::operator<(const char16_t* other) const
+{
+    return strcmp16(mString, other) < 0;
+}
+
+inline bool String16::operator<=(const char16_t* other) const
+{
+    return strcmp16(mString, other) <= 0;
+}
+
+inline bool String16::operator==(const char16_t* other) const
+{
+    return strcmp16(mString, other) == 0;
+}
+
+inline bool String16::operator!=(const char16_t* other) const
+{
+    return strcmp16(mString, other) != 0;
+}
+
+inline bool String16::operator>=(const char16_t* other) const
+{
+    return strcmp16(mString, other) >= 0;
+}
+
+inline bool String16::operator>(const char16_t* other) const
+{
+    return strcmp16(mString, other) > 0;
+}
+
+inline String16::operator const char16_t*() const
+{
+    return mString;
+}
+
+}; // namespace android
+
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_STRING16_H
diff --git a/package/utils/adbd/src/include/utils/String8.h b/package/utils/adbd/src/include/utils/String8.h
new file mode 100644
index 0000000..ecfcf10
--- /dev/null
+++ b/package/utils/adbd/src/include/utils/String8.h
@@ -0,0 +1,408 @@
+/*
+ * Copyright (C) 2005 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 ANDROID_STRING8_H
+#define ANDROID_STRING8_H
+
+#include <utils/Errors.h>
+#include <utils/SharedBuffer.h>
+#include <utils/Unicode.h>
+#include <utils/TypeHelpers.h>
+
+#include <string.h> // for strcmp
+#include <stdarg.h>
+
+// ---------------------------------------------------------------------------
+
+namespace android {
+
+class String16;
+class TextOutput;
+
+//! This is a string holding UTF-8 characters. Does not allow the value more
+// than 0x10FFFF, which is not valid unicode codepoint.
+class String8
+{
+public:
+    /* use String8(StaticLinkage) if you're statically linking against
+     * libutils and declaring an empty static String8, e.g.:
+     *
+     *   static String8 sAStaticEmptyString(String8::kEmptyString);
+     *   static String8 sAnotherStaticEmptyString(sAStaticEmptyString);
+     */
+    enum StaticLinkage { kEmptyString };
+
+                                String8();
+    explicit                    String8(StaticLinkage);
+                                String8(const String8& o);
+    explicit                    String8(const char* o);
+    explicit                    String8(const char* o, size_t numChars);
+    
+    explicit                    String8(const String16& o);
+    explicit                    String8(const char16_t* o);
+    explicit                    String8(const char16_t* o, size_t numChars);
+    explicit                    String8(const char32_t* o);
+    explicit                    String8(const char32_t* o, size_t numChars);
+                                ~String8();
+
+    static inline const String8 empty();
+
+    static String8              format(const char* fmt, ...) __attribute__((format (printf, 1, 2)));
+    static String8              formatV(const char* fmt, va_list args);
+
+    inline  const char*         string() const;
+    inline  size_t              size() const;
+    inline  size_t              length() const;
+    inline  size_t              bytes() const;
+    inline  bool                isEmpty() const;
+    
+    inline  const SharedBuffer* sharedBuffer() const;
+    
+            void                clear();
+
+            void                setTo(const String8& other);
+            status_t            setTo(const char* other);
+            status_t            setTo(const char* other, size_t numChars);
+            status_t            setTo(const char16_t* other, size_t numChars);
+            status_t            setTo(const char32_t* other,
+                                      size_t length);
+
+            status_t            append(const String8& other);
+            status_t            append(const char* other);
+            status_t            append(const char* other, size_t numChars);
+
+            status_t            appendFormat(const char* fmt, ...)
+                    __attribute__((format (printf, 2, 3)));
+            status_t            appendFormatV(const char* fmt, va_list args);
+
+            // Note that this function takes O(N) time to calculate the value.
+            // No cache value is stored.
+            size_t              getUtf32Length() const;
+            int32_t             getUtf32At(size_t index,
+                                           size_t *next_index) const;
+            void                getUtf32(char32_t* dst) const;
+
+    inline  String8&            operator=(const String8& other);
+    inline  String8&            operator=(const char* other);
+    
+    inline  String8&            operator+=(const String8& other);
+    inline  String8             operator+(const String8& other) const;
+    
+    inline  String8&            operator+=(const char* other);
+    inline  String8             operator+(const char* other) const;
+
+    inline  int                 compare(const String8& other) const;
+
+    inline  bool                operator<(const String8& other) const;
+    inline  bool                operator<=(const String8& other) const;
+    inline  bool                operator==(const String8& other) const;
+    inline  bool                operator!=(const String8& other) const;
+    inline  bool                operator>=(const String8& other) const;
+    inline  bool                operator>(const String8& other) const;
+    
+    inline  bool                operator<(const char* other) const;
+    inline  bool                operator<=(const char* other) const;
+    inline  bool                operator==(const char* other) const;
+    inline  bool                operator!=(const char* other) const;
+    inline  bool                operator>=(const char* other) const;
+    inline  bool                operator>(const char* other) const;
+    
+    inline                      operator const char*() const;
+    
+            char*               lockBuffer(size_t size);
+            void                unlockBuffer();
+            status_t            unlockBuffer(size_t size);
+            
+            // return the index of the first byte of other in this at or after
+            // start, or -1 if not found
+            ssize_t             find(const char* other, size_t start = 0) const;
+
+            // return true if this string contains the specified substring
+    inline  bool                contains(const char* other) const;
+
+            // removes all occurrence of the specified substring
+            // returns true if any were found and removed
+            bool                removeAll(const char* other);
+
+            void                toLower();
+            void                toLower(size_t start, size_t numChars);
+            void                toUpper();
+            void                toUpper(size_t start, size_t numChars);
+
+
+    /*
+     * These methods operate on the string as if it were a path name.
+     */
+
+    /*
+     * Set the filename field to a specific value.
+     *
+     * Normalizes the filename, removing a trailing '/' if present.
+     */
+    void setPathName(const char* name);
+    void setPathName(const char* name, size_t numChars);
+
+    /*
+     * Get just the filename component.
+     *
+     * "/tmp/foo/bar.c" --> "bar.c"
+     */
+    String8 getPathLeaf(void) const;
+
+    /*
+     * Remove the last (file name) component, leaving just the directory
+     * name.
+     *
+     * "/tmp/foo/bar.c" --> "/tmp/foo"
+     * "/tmp" --> "" // ????? shouldn't this be "/" ???? XXX
+     * "bar.c" --> ""
+     */
+    String8 getPathDir(void) const;
+
+    /*
+     * Retrieve the front (root dir) component.  Optionally also return the
+     * remaining components.
+     *
+     * "/tmp/foo/bar.c" --> "tmp" (remain = "foo/bar.c")
+     * "/tmp" --> "tmp" (remain = "")
+     * "bar.c" --> "bar.c" (remain = "")
+     */
+    String8 walkPath(String8* outRemains = NULL) const;
+
+    /*
+     * Return the filename extension.  This is the last '.' and any number
+     * of characters that follow it.  The '.' is included in case we
+     * decide to expand our definition of what constitutes an extension.
+     *
+     * "/tmp/foo/bar.c" --> ".c"
+     * "/tmp" --> ""
+     * "/tmp/foo.bar/baz" --> ""
+     * "foo.jpeg" --> ".jpeg"
+     * "foo." --> ""
+     */
+    String8 getPathExtension(void) const;
+
+    /*
+     * Return the path without the extension.  Rules for what constitutes
+     * an extension are described in the comment for getPathExtension().
+     *
+     * "/tmp/foo/bar.c" --> "/tmp/foo/bar"
+     */
+    String8 getBasePath(void) const;
+
+    /*
+     * Add a component to the pathname.  We guarantee that there is
+     * exactly one path separator between the old path and the new.
+     * If there is no existing name, we just copy the new name in.
+     *
+     * If leaf is a fully qualified path (i.e. starts with '/', it
+     * replaces whatever was there before.
+     */
+    String8& appendPath(const char* leaf);
+    String8& appendPath(const String8& leaf)  { return appendPath(leaf.string()); }
+
+    /*
+     * Like appendPath(), but does not affect this string.  Returns a new one instead.
+     */
+    String8 appendPathCopy(const char* leaf) const
+                                             { String8 p(*this); p.appendPath(leaf); return p; }
+    String8 appendPathCopy(const String8& leaf) const { return appendPathCopy(leaf.string()); }
+
+    /*
+     * Converts all separators in this string to /, the default path separator.
+     *
+     * If the default OS separator is backslash, this converts all
+     * backslashes to slashes, in-place. Otherwise it does nothing.
+     * Returns self.
+     */
+    String8& convertToResPath();
+
+private:
+            status_t            real_append(const char* other, size_t numChars);
+            char*               find_extension(void) const;
+
+            const char* mString;
+};
+
+// String8 can be trivially moved using memcpy() because moving does not
+// require any change to the underlying SharedBuffer contents or reference count.
+ANDROID_TRIVIAL_MOVE_TRAIT(String8)
+
+// ---------------------------------------------------------------------------
+// No user servicable parts below.
+
+inline int compare_type(const String8& lhs, const String8& rhs)
+{
+    return lhs.compare(rhs);
+}
+
+inline int strictly_order_type(const String8& lhs, const String8& rhs)
+{
+    return compare_type(lhs, rhs) < 0;
+}
+
+inline const String8 String8::empty() {
+    return String8();
+}
+
+inline const char* String8::string() const
+{
+    return mString;
+}
+
+inline size_t String8::length() const
+{
+    return SharedBuffer::sizeFromData(mString)-1;
+}
+
+inline size_t String8::size() const
+{
+    return length();
+}
+
+inline bool String8::isEmpty() const
+{
+    return length() == 0;
+}
+
+inline size_t String8::bytes() const
+{
+    return SharedBuffer::sizeFromData(mString)-1;
+}
+
+inline const SharedBuffer* String8::sharedBuffer() const
+{
+    return SharedBuffer::bufferFromData(mString);
+}
+
+inline bool String8::contains(const char* other) const
+{
+    return find(other) >= 0;
+}
+
+inline String8& String8::operator=(const String8& other)
+{
+    setTo(other);
+    return *this;
+}
+
+inline String8& String8::operator=(const char* other)
+{
+    setTo(other);
+    return *this;
+}
+
+inline String8& String8::operator+=(const String8& other)
+{
+    append(other);
+    return *this;
+}
+
+inline String8 String8::operator+(const String8& other) const
+{
+    String8 tmp(*this);
+    tmp += other;
+    return tmp;
+}
+
+inline String8& String8::operator+=(const char* other)
+{
+    append(other);
+    return *this;
+}
+
+inline String8 String8::operator+(const char* other) const
+{
+    String8 tmp(*this);
+    tmp += other;
+    return tmp;
+}
+
+inline int String8::compare(const String8& other) const
+{
+    return strcmp(mString, other.mString);
+}
+
+inline bool String8::operator<(const String8& other) const
+{
+    return strcmp(mString, other.mString) < 0;
+}
+
+inline bool String8::operator<=(const String8& other) const
+{
+    return strcmp(mString, other.mString) <= 0;
+}
+
+inline bool String8::operator==(const String8& other) const
+{
+    return strcmp(mString, other.mString) == 0;
+}
+
+inline bool String8::operator!=(const String8& other) const
+{
+    return strcmp(mString, other.mString) != 0;
+}
+
+inline bool String8::operator>=(const String8& other) const
+{
+    return strcmp(mString, other.mString) >= 0;
+}
+
+inline bool String8::operator>(const String8& other) const
+{
+    return strcmp(mString, other.mString) > 0;
+}
+
+inline bool String8::operator<(const char* other) const
+{
+    return strcmp(mString, other) < 0;
+}
+
+inline bool String8::operator<=(const char* other) const
+{
+    return strcmp(mString, other) <= 0;
+}
+
+inline bool String8::operator==(const char* other) const
+{
+    return strcmp(mString, other) == 0;
+}
+
+inline bool String8::operator!=(const char* other) const
+{
+    return strcmp(mString, other) != 0;
+}
+
+inline bool String8::operator>=(const char* other) const
+{
+    return strcmp(mString, other) >= 0;
+}
+
+inline bool String8::operator>(const char* other) const
+{
+    return strcmp(mString, other) > 0;
+}
+
+inline String8::operator const char*() const
+{
+    return mString;
+}
+
+}  // namespace android
+
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_STRING8_H
diff --git a/package/utils/adbd/src/include/utils/StrongPointer.h b/package/utils/adbd/src/include/utils/StrongPointer.h
new file mode 100644
index 0000000..aba9577
--- /dev/null
+++ b/package/utils/adbd/src/include/utils/StrongPointer.h
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2005 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 ANDROID_STRONG_POINTER_H
+#define ANDROID_STRONG_POINTER_H
+
+#include <cutils/atomic.h>
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <stdlib.h>
+
+// ---------------------------------------------------------------------------
+namespace android {
+
+template<typename T> class wp;
+
+// ---------------------------------------------------------------------------
+
+#define COMPARE(_op_)                                           \
+inline bool operator _op_ (const sp<T>& o) const {              \
+    return m_ptr _op_ o.m_ptr;                                  \
+}                                                               \
+inline bool operator _op_ (const T* o) const {                  \
+    return m_ptr _op_ o;                                        \
+}                                                               \
+template<typename U>                                            \
+inline bool operator _op_ (const sp<U>& o) const {              \
+    return m_ptr _op_ o.m_ptr;                                  \
+}                                                               \
+template<typename U>                                            \
+inline bool operator _op_ (const U* o) const {                  \
+    return m_ptr _op_ o;                                        \
+}                                                               \
+inline bool operator _op_ (const wp<T>& o) const {              \
+    return m_ptr _op_ o.m_ptr;                                  \
+}                                                               \
+template<typename U>                                            \
+inline bool operator _op_ (const wp<U>& o) const {              \
+    return m_ptr _op_ o.m_ptr;                                  \
+}
+
+// ---------------------------------------------------------------------------
+
+template<typename T>
+class sp {
+public:
+    inline sp() : m_ptr(0) { }
+
+    sp(T* other);
+    sp(const sp<T>& other);
+    template<typename U> sp(U* other);
+    template<typename U> sp(const sp<U>& other);
+
+    ~sp();
+
+    // Assignment
+
+    sp& operator = (T* other);
+    sp& operator = (const sp<T>& other);
+
+    template<typename U> sp& operator = (const sp<U>& other);
+    template<typename U> sp& operator = (U* other);
+
+    //! Special optimization for use by ProcessState (and nobody else).
+    void force_set(T* other);
+
+    // Reset
+
+    void clear();
+
+    // Accessors
+
+    inline  T&      operator* () const  { return *m_ptr; }
+    inline  T*      operator-> () const { return m_ptr;  }
+    inline  T*      get() const         { return m_ptr; }
+
+    // Operators
+
+    COMPARE(==)
+    COMPARE(!=)
+    COMPARE(>)
+    COMPARE(<)
+    COMPARE(<=)
+    COMPARE(>=)
+
+private:    
+    template<typename Y> friend class sp;
+    template<typename Y> friend class wp;
+    void set_pointer(T* ptr);
+    T* m_ptr;
+};
+
+#undef COMPARE
+
+// ---------------------------------------------------------------------------
+// No user serviceable parts below here.
+
+template<typename T>
+sp<T>::sp(T* other)
+        : m_ptr(other) {
+    if (other)
+        other->incStrong(this);
+}
+
+template<typename T>
+sp<T>::sp(const sp<T>& other)
+        : m_ptr(other.m_ptr) {
+    if (m_ptr)
+        m_ptr->incStrong(this);
+}
+
+template<typename T> template<typename U>
+sp<T>::sp(U* other)
+        : m_ptr(other) {
+    if (other)
+        ((T*) other)->incStrong(this);
+}
+
+template<typename T> template<typename U>
+sp<T>::sp(const sp<U>& other)
+        : m_ptr(other.m_ptr) {
+    if (m_ptr)
+        m_ptr->incStrong(this);
+}
+
+template<typename T>
+sp<T>::~sp() {
+    if (m_ptr)
+        m_ptr->decStrong(this);
+}
+
+template<typename T>
+sp<T>& sp<T>::operator =(const sp<T>& other) {
+    T* otherPtr(other.m_ptr);
+    if (otherPtr)
+        otherPtr->incStrong(this);
+    if (m_ptr)
+        m_ptr->decStrong(this);
+    m_ptr = otherPtr;
+    return *this;
+}
+
+template<typename T>
+sp<T>& sp<T>::operator =(T* other) {
+    if (other)
+        other->incStrong(this);
+    if (m_ptr)
+        m_ptr->decStrong(this);
+    m_ptr = other;
+    return *this;
+}
+
+template<typename T> template<typename U>
+sp<T>& sp<T>::operator =(const sp<U>& other) {
+    T* otherPtr(other.m_ptr);
+    if (otherPtr)
+        otherPtr->incStrong(this);
+    if (m_ptr)
+        m_ptr->decStrong(this);
+    m_ptr = otherPtr;
+    return *this;
+}
+
+template<typename T> template<typename U>
+sp<T>& sp<T>::operator =(U* other) {
+    if (other)
+        ((T*) other)->incStrong(this);
+    if (m_ptr)
+        m_ptr->decStrong(this);
+    m_ptr = other;
+    return *this;
+}
+
+template<typename T>
+void sp<T>::force_set(T* other) {
+    other->forceIncStrong(this);
+    m_ptr = other;
+}
+
+template<typename T>
+void sp<T>::clear() {
+    if (m_ptr) {
+        m_ptr->decStrong(this);
+        m_ptr = 0;
+    }
+}
+
+template<typename T>
+void sp<T>::set_pointer(T* ptr) {
+    m_ptr = ptr;
+}
+
+}; // namespace android
+
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_STRONG_POINTER_H
diff --git a/package/utils/adbd/src/include/utils/SystemClock.h b/package/utils/adbd/src/include/utils/SystemClock.h
new file mode 100644
index 0000000..01db340
--- /dev/null
+++ b/package/utils/adbd/src/include/utils/SystemClock.h
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_UTILS_SYSTEMCLOCK_H
+#define ANDROID_UTILS_SYSTEMCLOCK_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+namespace android {
+
+int64_t uptimeMillis();
+int64_t elapsedRealtime();
+int64_t elapsedRealtimeNano();
+
+}; // namespace android
+
+#endif // ANDROID_UTILS_SYSTEMCLOCK_H
+
diff --git a/package/utils/adbd/src/include/utils/Thread.h b/package/utils/adbd/src/include/utils/Thread.h
new file mode 100644
index 0000000..df30611
--- /dev/null
+++ b/package/utils/adbd/src/include/utils/Thread.h
@@ -0,0 +1,116 @@
+/*
+ * 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 _LIBS_UTILS_THREAD_H
+#define _LIBS_UTILS_THREAD_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <time.h>
+
+#if defined(HAVE_PTHREADS)
+# include <pthread.h>
+#endif
+
+#include <utils/Condition.h>
+#include <utils/Errors.h>
+#include <utils/Mutex.h>
+#include <utils/RefBase.h>
+#include <utils/Timers.h>
+#include <utils/ThreadDefs.h>
+
+// ---------------------------------------------------------------------------
+namespace android {
+// ---------------------------------------------------------------------------
+
+class Thread : virtual public RefBase
+{
+public:
+    // Create a Thread object, but doesn't create or start the associated
+    // thread. See the run() method.
+                        Thread(bool canCallJava = true);
+    virtual             ~Thread();
+
+    // Start the thread in threadLoop() which needs to be implemented.
+    virtual status_t    run(    const char* name = 0,
+                                int32_t priority = PRIORITY_DEFAULT,
+                                size_t stack = 0);
+    
+    // Ask this object's thread to exit. This function is asynchronous, when the
+    // function returns the thread might still be running. Of course, this
+    // function can be called from a different thread.
+    virtual void        requestExit();
+
+    // Good place to do one-time initializations
+    virtual status_t    readyToRun();
+    
+    // Call requestExit() and wait until this object's thread exits.
+    // BE VERY CAREFUL of deadlocks. In particular, it would be silly to call
+    // this function from this object's thread. Will return WOULD_BLOCK in
+    // that case.
+            status_t    requestExitAndWait();
+
+    // Wait until this object's thread exits. Returns immediately if not yet running.
+    // Do not call from this object's thread; will return WOULD_BLOCK in that case.
+            status_t    join();
+
+    // Indicates whether this thread is running or not.
+            bool        isRunning() const;
+
+#ifdef HAVE_ANDROID_OS
+    // Return the thread's kernel ID, same as the thread itself calling gettid() or
+    // androidGetTid(), or -1 if the thread is not running.
+            pid_t       getTid() const;
+#endif
+
+protected:
+    // exitPending() returns true if requestExit() has been called.
+            bool        exitPending() const;
+    
+private:
+    // Derived class must implement threadLoop(). The thread starts its life
+    // here. There are two ways of using the Thread object:
+    // 1) loop: if threadLoop() returns true, it will be called again if
+    //          requestExit() wasn't called.
+    // 2) once: if threadLoop() returns false, the thread will exit upon return.
+    virtual bool        threadLoop() = 0;
+
+private:
+    Thread& operator=(const Thread&);
+    static  int             _threadLoop(void* user);
+    const   bool            mCanCallJava;
+    // always hold mLock when reading or writing
+            thread_id_t     mThread;
+    mutable Mutex           mLock;
+            Condition       mThreadExitedCondition;
+            status_t        mStatus;
+    // note that all accesses of mExitPending and mRunning need to hold mLock
+    volatile bool           mExitPending;
+    volatile bool           mRunning;
+            sp<Thread>      mHoldSelf;
+#ifdef HAVE_ANDROID_OS
+    // legacy for debugging, not used by getTid() as it is set by the child thread
+    // and so is not initialized until the child reaches that point
+            pid_t           mTid;
+#endif
+};
+
+
+}; // namespace android
+
+// ---------------------------------------------------------------------------
+#endif // _LIBS_UTILS_THREAD_H
+// ---------------------------------------------------------------------------
diff --git a/package/utils/adbd/src/include/utils/ThreadDefs.h b/package/utils/adbd/src/include/utils/ThreadDefs.h
new file mode 100644
index 0000000..9711c13
--- /dev/null
+++ b/package/utils/adbd/src/include/utils/ThreadDefs.h
@@ -0,0 +1,70 @@
+/*
+ * 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 _LIBS_UTILS_THREAD_DEFS_H
+#define _LIBS_UTILS_THREAD_DEFS_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <system/graphics.h>
+#include <system/thread_defs.h>
+
+// ---------------------------------------------------------------------------
+// C API
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void* android_thread_id_t;
+
+typedef int (*android_thread_func_t)(void*);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+// ---------------------------------------------------------------------------
+// C++ API
+#ifdef __cplusplus
+namespace android {
+// ---------------------------------------------------------------------------
+
+typedef android_thread_id_t thread_id_t;
+typedef android_thread_func_t thread_func_t;
+
+enum {
+    PRIORITY_LOWEST         = ANDROID_PRIORITY_LOWEST,
+    PRIORITY_BACKGROUND     = ANDROID_PRIORITY_BACKGROUND,
+    PRIORITY_NORMAL         = ANDROID_PRIORITY_NORMAL,
+    PRIORITY_FOREGROUND     = ANDROID_PRIORITY_FOREGROUND,
+    PRIORITY_DISPLAY        = ANDROID_PRIORITY_DISPLAY,
+    PRIORITY_URGENT_DISPLAY = ANDROID_PRIORITY_URGENT_DISPLAY,
+    PRIORITY_AUDIO          = ANDROID_PRIORITY_AUDIO,
+    PRIORITY_URGENT_AUDIO   = ANDROID_PRIORITY_URGENT_AUDIO,
+    PRIORITY_HIGHEST        = ANDROID_PRIORITY_HIGHEST,
+    PRIORITY_DEFAULT        = ANDROID_PRIORITY_DEFAULT,
+    PRIORITY_MORE_FAVORABLE = ANDROID_PRIORITY_MORE_FAVORABLE,
+    PRIORITY_LESS_FAVORABLE = ANDROID_PRIORITY_LESS_FAVORABLE,
+};
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+#endif  // __cplusplus
+// ---------------------------------------------------------------------------
+
+
+#endif // _LIBS_UTILS_THREAD_DEFS_H
diff --git a/package/utils/adbd/src/include/utils/Timers.h b/package/utils/adbd/src/include/utils/Timers.h
new file mode 100644
index 0000000..d015421
--- /dev/null
+++ b/package/utils/adbd/src/include/utils/Timers.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+//
+// Timer functions.
+//
+#ifndef _LIBS_UTILS_TIMERS_H
+#define _LIBS_UTILS_TIMERS_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <sys/time.h>
+
+// ------------------------------------------------------------------
+// C API
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef int64_t nsecs_t;       // nano-seconds
+
+static inline nsecs_t seconds_to_nanoseconds(nsecs_t secs)
+{
+    return secs*1000000000;
+}
+
+static inline nsecs_t milliseconds_to_nanoseconds(nsecs_t secs)
+{
+    return secs*1000000;
+}
+
+static inline nsecs_t microseconds_to_nanoseconds(nsecs_t secs)
+{
+    return secs*1000;
+}
+
+static inline nsecs_t nanoseconds_to_seconds(nsecs_t secs)
+{
+    return secs/1000000000;
+}
+
+static inline nsecs_t nanoseconds_to_milliseconds(nsecs_t secs)
+{
+    return secs/1000000;
+}
+
+static inline nsecs_t nanoseconds_to_microseconds(nsecs_t secs)
+{
+    return secs/1000;
+}
+
+static inline nsecs_t s2ns(nsecs_t v)  {return seconds_to_nanoseconds(v);}
+static inline nsecs_t ms2ns(nsecs_t v) {return milliseconds_to_nanoseconds(v);}
+static inline nsecs_t us2ns(nsecs_t v) {return microseconds_to_nanoseconds(v);}
+static inline nsecs_t ns2s(nsecs_t v)  {return nanoseconds_to_seconds(v);}
+static inline nsecs_t ns2ms(nsecs_t v) {return nanoseconds_to_milliseconds(v);}
+static inline nsecs_t ns2us(nsecs_t v) {return nanoseconds_to_microseconds(v);}
+
+static inline nsecs_t seconds(nsecs_t v)      { return s2ns(v); }
+static inline nsecs_t milliseconds(nsecs_t v) { return ms2ns(v); }
+static inline nsecs_t microseconds(nsecs_t v) { return us2ns(v); }
+
+enum {
+    SYSTEM_TIME_REALTIME = 0,  // system-wide realtime clock
+    SYSTEM_TIME_MONOTONIC = 1, // monotonic time since unspecified starting point
+    SYSTEM_TIME_PROCESS = 2,   // high-resolution per-process clock
+    SYSTEM_TIME_THREAD = 3,    // high-resolution per-thread clock
+    SYSTEM_TIME_BOOTTIME = 4   // same as SYSTEM_TIME_MONOTONIC, but including CPU suspend time
+};
+
+// return the system-time according to the specified clock
+#ifdef __cplusplus
+nsecs_t systemTime(int clock = SYSTEM_TIME_MONOTONIC);
+#else
+nsecs_t systemTime(int clock);
+#endif // def __cplusplus
+
+/**
+ * Returns the number of milliseconds to wait between the reference time and the timeout time.
+ * If the timeout is in the past relative to the reference time, returns 0.
+ * If the timeout is more than INT_MAX milliseconds in the future relative to the reference time,
+ * such as when timeoutTime == LLONG_MAX, returns -1 to indicate an infinite timeout delay.
+ * Otherwise, returns the difference between the reference time and timeout time
+ * rounded up to the next millisecond.
+ */
+int toMillisecondTimeoutDelay(nsecs_t referenceTime, nsecs_t timeoutTime);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _LIBS_UTILS_TIMERS_H
diff --git a/package/utils/adbd/src/include/utils/Tokenizer.h b/package/utils/adbd/src/include/utils/Tokenizer.h
new file mode 100644
index 0000000..bb25f37
--- /dev/null
+++ b/package/utils/adbd/src/include/utils/Tokenizer.h
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2010 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 _UTILS_TOKENIZER_H
+#define _UTILS_TOKENIZER_H
+
+#include <assert.h>
+#include <utils/Errors.h>
+#include <utils/FileMap.h>
+#include <utils/String8.h>
+
+namespace android {
+
+/**
+ * A simple tokenizer for loading and parsing ASCII text files line by line.
+ */
+class Tokenizer {
+    Tokenizer(const String8& filename, FileMap* fileMap, char* buffer,
+            bool ownBuffer, size_t length);
+
+public:
+    ~Tokenizer();
+
+    /**
+     * Opens a file and maps it into memory.
+     *
+     * Returns NO_ERROR and a tokenizer for the file, if successful.
+     * Otherwise returns an error and sets outTokenizer to NULL.
+     */
+    static status_t open(const String8& filename, Tokenizer** outTokenizer);
+
+    /**
+     * Prepares to tokenize the contents of a string.
+     *
+     * Returns NO_ERROR and a tokenizer for the string, if successful.
+     * Otherwise returns an error and sets outTokenizer to NULL.
+     */
+    static status_t fromContents(const String8& filename,
+            const char* contents, Tokenizer** outTokenizer);
+
+    /**
+     * Returns true if at the end of the file.
+     */
+    inline bool isEof() const { return mCurrent == getEnd(); }
+
+    /**
+     * Returns true if at the end of the line or end of the file.
+     */
+    inline bool isEol() const { return isEof() || *mCurrent == '\n'; }
+
+    /**
+     * Gets the name of the file.
+     */
+    inline String8 getFilename() const { return mFilename; }
+
+    /**
+     * Gets a 1-based line number index for the current position.
+     */
+    inline int32_t getLineNumber() const { return mLineNumber; }
+
+    /**
+     * Formats a location string consisting of the filename and current line number.
+     * Returns a string like "MyFile.txt:33".
+     */
+    String8 getLocation() const;
+
+    /**
+     * Gets the character at the current position.
+     * Returns null at end of file.
+     */
+    inline char peekChar() const { return isEof() ? '\0' : *mCurrent; }
+
+    /**
+     * Gets the remainder of the current line as a string, excluding the newline character.
+     */
+    String8 peekRemainderOfLine() const;
+
+    /**
+     * Gets the character at the current position and advances past it.
+     * Returns null at end of file.
+     */
+    inline char nextChar() { return isEof() ? '\0' : *(mCurrent++); }
+
+    /**
+     * Gets the next token on this line stopping at the specified delimiters
+     * or the end of the line whichever comes first and advances past it.
+     * Also stops at embedded nulls.
+     * Returns the token or an empty string if the current character is a delimiter
+     * or is at the end of the line.
+     */
+    String8 nextToken(const char* delimiters);
+
+    /**
+     * Advances to the next line.
+     * Does nothing if already at the end of the file.
+     */
+    void nextLine();
+
+    /**
+     * Skips over the specified delimiters in the line.
+     * Also skips embedded nulls.
+     */
+    void skipDelimiters(const char* delimiters);
+
+private:
+    Tokenizer(const Tokenizer& other); // not copyable
+
+    String8 mFilename;
+    FileMap* mFileMap;
+    char* mBuffer;
+    bool mOwnBuffer;
+    size_t mLength;
+
+    const char* mCurrent;
+    int32_t mLineNumber;
+
+    inline const char* getEnd() const { return mBuffer + mLength; }
+
+};
+
+} // namespace android
+
+#endif // _UTILS_TOKENIZER_H
diff --git a/package/utils/adbd/src/include/utils/Trace.h b/package/utils/adbd/src/include/utils/Trace.h
new file mode 100644
index 0000000..6ee343d
--- /dev/null
+++ b/package/utils/adbd/src/include/utils/Trace.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2012 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 ANDROID_TRACE_H
+#define ANDROID_TRACE_H
+
+#ifdef HAVE_ANDROID_OS
+
+#include <fcntl.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <cutils/compiler.h>
+#include <utils/threads.h>
+#include <cutils/trace.h>
+
+// See <cutils/trace.h> for more ATRACE_* macros.
+
+// ATRACE_NAME traces the beginning and end of the current scope.  To trace
+// the correct start and end times this macro should be declared first in the
+// scope body.
+#define ATRACE_NAME(name) android::ScopedTrace ___tracer(ATRACE_TAG, name)
+// ATRACE_CALL is an ATRACE_NAME that uses the current function name.
+#define ATRACE_CALL() ATRACE_NAME(__FUNCTION__)
+
+namespace android {
+
+class ScopedTrace {
+public:
+inline ScopedTrace(uint64_t tag, const char* name)
+    : mTag(tag) {
+    atrace_begin(mTag,name);
+}
+
+inline ~ScopedTrace() {
+    atrace_end(mTag);
+}
+
+private:
+    uint64_t mTag;
+};
+
+}; // namespace android
+
+#else // HAVE_ANDROID_OS
+
+#define ATRACE_NAME(...)
+#define ATRACE_CALL()
+
+#endif // HAVE_ANDROID_OS
+
+#endif // ANDROID_TRACE_H
diff --git a/package/utils/adbd/src/include/utils/TypeHelpers.h b/package/utils/adbd/src/include/utils/TypeHelpers.h
new file mode 100644
index 0000000..13c9081
--- /dev/null
+++ b/package/utils/adbd/src/include/utils/TypeHelpers.h
@@ -0,0 +1,302 @@
+/*
+ * Copyright (C) 2005 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 ANDROID_TYPE_HELPERS_H
+#define ANDROID_TYPE_HELPERS_H
+
+#include <new>
+#include <stdint.h>
+#include <string.h>
+#include <sys/types.h>
+
+// ---------------------------------------------------------------------------
+
+namespace android {
+
+/*
+ * Types traits
+ */
+
+template <typename T> struct trait_trivial_ctor { enum { value = false }; };
+template <typename T> struct trait_trivial_dtor { enum { value = false }; };
+template <typename T> struct trait_trivial_copy { enum { value = false }; };
+template <typename T> struct trait_trivial_move { enum { value = false }; };
+template <typename T> struct trait_pointer      { enum { value = false }; };    
+template <typename T> struct trait_pointer<T*>  { enum { value = true }; };
+
+template <typename TYPE>
+struct traits {
+    enum {
+        // whether this type is a pointer
+        is_pointer          = trait_pointer<TYPE>::value,
+        // whether this type's constructor is a no-op
+        has_trivial_ctor    = is_pointer || trait_trivial_ctor<TYPE>::value,
+        // whether this type's destructor is a no-op
+        has_trivial_dtor    = is_pointer || trait_trivial_dtor<TYPE>::value,
+        // whether this type type can be copy-constructed with memcpy
+        has_trivial_copy    = is_pointer || trait_trivial_copy<TYPE>::value,
+        // whether this type can be moved with memmove
+        has_trivial_move    = is_pointer || trait_trivial_move<TYPE>::value
+    };
+};
+
+template <typename T, typename U>
+struct aggregate_traits {
+    enum {
+        is_pointer          = false,
+        has_trivial_ctor    = 
+            traits<T>::has_trivial_ctor && traits<U>::has_trivial_ctor,
+        has_trivial_dtor    = 
+            traits<T>::has_trivial_dtor && traits<U>::has_trivial_dtor,
+        has_trivial_copy    = 
+            traits<T>::has_trivial_copy && traits<U>::has_trivial_copy,
+        has_trivial_move    = 
+            traits<T>::has_trivial_move && traits<U>::has_trivial_move
+    };
+};
+
+#define ANDROID_TRIVIAL_CTOR_TRAIT( T ) \
+    template<> struct trait_trivial_ctor< T >   { enum { value = true }; };
+
+#define ANDROID_TRIVIAL_DTOR_TRAIT( T ) \
+    template<> struct trait_trivial_dtor< T >   { enum { value = true }; };
+
+#define ANDROID_TRIVIAL_COPY_TRAIT( T ) \
+    template<> struct trait_trivial_copy< T >   { enum { value = true }; };
+
+#define ANDROID_TRIVIAL_MOVE_TRAIT( T ) \
+    template<> struct trait_trivial_move< T >   { enum { value = true }; };
+
+#define ANDROID_BASIC_TYPES_TRAITS( T ) \
+    ANDROID_TRIVIAL_CTOR_TRAIT( T ) \
+    ANDROID_TRIVIAL_DTOR_TRAIT( T ) \
+    ANDROID_TRIVIAL_COPY_TRAIT( T ) \
+    ANDROID_TRIVIAL_MOVE_TRAIT( T )
+
+// ---------------------------------------------------------------------------
+
+/*
+ * basic types traits
+ */
+
+ANDROID_BASIC_TYPES_TRAITS( void )
+ANDROID_BASIC_TYPES_TRAITS( bool )
+ANDROID_BASIC_TYPES_TRAITS( char )
+ANDROID_BASIC_TYPES_TRAITS( unsigned char )
+ANDROID_BASIC_TYPES_TRAITS( short )
+ANDROID_BASIC_TYPES_TRAITS( unsigned short )
+ANDROID_BASIC_TYPES_TRAITS( int )
+ANDROID_BASIC_TYPES_TRAITS( unsigned int )
+ANDROID_BASIC_TYPES_TRAITS( long )
+ANDROID_BASIC_TYPES_TRAITS( unsigned long )
+ANDROID_BASIC_TYPES_TRAITS( long long )
+ANDROID_BASIC_TYPES_TRAITS( unsigned long long )
+ANDROID_BASIC_TYPES_TRAITS( float )
+ANDROID_BASIC_TYPES_TRAITS( double )
+
+// ---------------------------------------------------------------------------
+
+
+/*
+ * compare and order types
+ */
+
+template<typename TYPE> inline
+int strictly_order_type(const TYPE& lhs, const TYPE& rhs) {
+    return (lhs < rhs) ? 1 : 0;
+}
+
+template<typename TYPE> inline
+int compare_type(const TYPE& lhs, const TYPE& rhs) {
+    return strictly_order_type(rhs, lhs) - strictly_order_type(lhs, rhs);
+}
+
+/*
+ * create, destroy, copy and move types...
+ */
+
+template<typename TYPE> inline
+void construct_type(TYPE* p, size_t n) {
+    if (!traits<TYPE>::has_trivial_ctor) {
+        while (n--) {
+            new(p++) TYPE;
+        }
+    }
+}
+
+template<typename TYPE> inline
+void destroy_type(TYPE* p, size_t n) {
+    if (!traits<TYPE>::has_trivial_dtor) {
+        while (n--) {
+            p->~TYPE();
+            p++;
+        }
+    }
+}
+
+template<typename TYPE> inline
+void copy_type(TYPE* d, const TYPE* s, size_t n) {
+    if (!traits<TYPE>::has_trivial_copy) {
+        while (n--) {
+            new(d) TYPE(*s);
+            d++, s++;
+        }
+    } else {
+        memcpy(d,s,n*sizeof(TYPE));
+    }
+}
+
+template<typename TYPE> inline
+void splat_type(TYPE* where, const TYPE* what, size_t n) {
+    if (!traits<TYPE>::has_trivial_copy) {
+        while (n--) {
+            new(where) TYPE(*what);
+            where++;
+        }
+    } else {
+        while (n--) {
+            *where++ = *what;
+        }
+    }
+}
+
+template<typename TYPE> inline
+void move_forward_type(TYPE* d, const TYPE* s, size_t n = 1) {
+    if ((traits<TYPE>::has_trivial_dtor && traits<TYPE>::has_trivial_copy) 
+            || traits<TYPE>::has_trivial_move) 
+    {
+        memmove(d,s,n*sizeof(TYPE));
+    } else {
+        d += n;
+        s += n;
+        while (n--) {
+            --d, --s;
+            if (!traits<TYPE>::has_trivial_copy) {
+                new(d) TYPE(*s);
+            } else {
+                *d = *s;   
+            }
+            if (!traits<TYPE>::has_trivial_dtor) {
+                s->~TYPE();
+            }
+        }
+    }
+}
+
+template<typename TYPE> inline
+void move_backward_type(TYPE* d, const TYPE* s, size_t n = 1) {
+    if ((traits<TYPE>::has_trivial_dtor && traits<TYPE>::has_trivial_copy) 
+            || traits<TYPE>::has_trivial_move) 
+    {
+        memmove(d,s,n*sizeof(TYPE));
+    } else {
+        while (n--) {
+            if (!traits<TYPE>::has_trivial_copy) {
+                new(d) TYPE(*s);
+            } else {
+                *d = *s;   
+            }
+            if (!traits<TYPE>::has_trivial_dtor) {
+                s->~TYPE();
+            }
+            d++, s++;
+        }
+    }
+}
+
+// ---------------------------------------------------------------------------
+
+/*
+ * a key/value pair
+ */
+
+template <typename KEY, typename VALUE>
+struct key_value_pair_t {
+    typedef KEY key_t;
+    typedef VALUE value_t;
+
+    KEY     key;
+    VALUE   value;
+    key_value_pair_t() { }
+    key_value_pair_t(const key_value_pair_t& o) : key(o.key), value(o.value) { }
+    key_value_pair_t(const KEY& k, const VALUE& v) : key(k), value(v)  { }
+    key_value_pair_t(const KEY& k) : key(k) { }
+    inline bool operator < (const key_value_pair_t& o) const {
+        return strictly_order_type(key, o.key);
+    }
+    inline const KEY& getKey() const {
+        return key;
+    }
+    inline const VALUE& getValue() const {
+        return value;
+    }
+};
+
+template <typename K, typename V>
+struct trait_trivial_ctor< key_value_pair_t<K, V> >
+{ enum { value = aggregate_traits<K,V>::has_trivial_ctor }; };
+template <typename K, typename V>
+struct trait_trivial_dtor< key_value_pair_t<K, V> >
+{ enum { value = aggregate_traits<K,V>::has_trivial_dtor }; };
+template <typename K, typename V>
+struct trait_trivial_copy< key_value_pair_t<K, V> >
+{ enum { value = aggregate_traits<K,V>::has_trivial_copy }; };
+template <typename K, typename V>
+struct trait_trivial_move< key_value_pair_t<K, V> >
+{ enum { value = aggregate_traits<K,V>::has_trivial_move }; };
+
+// ---------------------------------------------------------------------------
+
+/*
+ * Hash codes.
+ */
+typedef uint32_t hash_t;
+
+template <typename TKey>
+hash_t hash_type(const TKey& key);
+
+/* Built-in hash code specializations.
+ * Assumes pointers are 32bit. */
+#define ANDROID_INT32_HASH(T) \
+        template <> inline hash_t hash_type(const T& value) { return hash_t(value); }
+#define ANDROID_INT64_HASH(T) \
+        template <> inline hash_t hash_type(const T& value) { \
+                return hash_t((value >> 32) ^ value); }
+#define ANDROID_REINTERPRET_HASH(T, R) \
+        template <> inline hash_t hash_type(const T& value) { \
+                return hash_type(*reinterpret_cast<const R*>(&value)); }
+
+ANDROID_INT32_HASH(bool)
+ANDROID_INT32_HASH(int8_t)
+ANDROID_INT32_HASH(uint8_t)
+ANDROID_INT32_HASH(int16_t)
+ANDROID_INT32_HASH(uint16_t)
+ANDROID_INT32_HASH(int32_t)
+ANDROID_INT32_HASH(uint32_t)
+ANDROID_INT64_HASH(int64_t)
+ANDROID_INT64_HASH(uint64_t)
+ANDROID_REINTERPRET_HASH(float, uint32_t)
+ANDROID_REINTERPRET_HASH(double, uint64_t)
+
+template <typename T> inline hash_t hash_type(T* const & value) {
+    return hash_type(uintptr_t(value));
+}
+
+}; // namespace android
+
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_TYPE_HELPERS_H
diff --git a/package/utils/adbd/src/include/utils/Unicode.h b/package/utils/adbd/src/include/utils/Unicode.h
new file mode 100644
index 0000000..5b98de2
--- /dev/null
+++ b/package/utils/adbd/src/include/utils/Unicode.h
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2005 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 ANDROID_UNICODE_H
+#define ANDROID_UNICODE_H
+
+#include <sys/types.h>
+#include <stdint.h>
+
+extern "C" {
+
+// Definitions exist in C++11
+#if defined __cplusplus && __cplusplus < 201103L
+typedef uint32_t char32_t;
+typedef uint16_t char16_t;
+#endif
+
+// Standard string functions on char16_t strings.
+int strcmp16(const char16_t *, const char16_t *);
+int strncmp16(const char16_t *s1, const char16_t *s2, size_t n);
+size_t strlen16(const char16_t *);
+size_t strnlen16(const char16_t *, size_t);
+char16_t *strcpy16(char16_t *, const char16_t *);
+char16_t *strncpy16(char16_t *, const char16_t *, size_t);
+
+// Version of comparison that supports embedded nulls.
+// This is different than strncmp() because we don't stop
+// at a nul character and consider the strings to be different
+// if the lengths are different (thus we need to supply the
+// lengths of both strings).  This can also be used when
+// your string is not nul-terminated as it will have the
+// equivalent result as strcmp16 (unlike strncmp16).
+int strzcmp16(const char16_t *s1, size_t n1, const char16_t *s2, size_t n2);
+
+// Version of strzcmp16 for comparing strings in different endianness.
+int strzcmp16_h_n(const char16_t *s1H, size_t n1, const char16_t *s2N, size_t n2);
+
+// Standard string functions on char32_t strings.
+size_t strlen32(const char32_t *);
+size_t strnlen32(const char32_t *, size_t);
+
+/**
+ * Measure the length of a UTF-32 string in UTF-8. If the string is invalid
+ * such as containing a surrogate character, -1 will be returned.
+ */
+ssize_t utf32_to_utf8_length(const char32_t *src, size_t src_len);
+
+/**
+ * Stores a UTF-8 string converted from "src" in "dst", if "dst_length" is not
+ * large enough to store the string, the part of the "src" string is stored
+ * into "dst" as much as possible. See the examples for more detail.
+ * Returns the size actually used for storing the string.
+ * dst" is not null-terminated when dst_len is fully used (like strncpy).
+ *
+ * Example 1
+ * "src" == \u3042\u3044 (\xE3\x81\x82\xE3\x81\x84)
+ * "src_len" == 2
+ * "dst_len" >= 7
+ * ->
+ * Returned value == 6
+ * "dst" becomes \xE3\x81\x82\xE3\x81\x84\0
+ * (note that "dst" is null-terminated)
+ *
+ * Example 2
+ * "src" == \u3042\u3044 (\xE3\x81\x82\xE3\x81\x84)
+ * "src_len" == 2
+ * "dst_len" == 5
+ * ->
+ * Returned value == 3
+ * "dst" becomes \xE3\x81\x82\0
+ * (note that "dst" is null-terminated, but \u3044 is not stored in "dst"
+ * since "dst" does not have enough size to store the character)
+ *
+ * Example 3
+ * "src" == \u3042\u3044 (\xE3\x81\x82\xE3\x81\x84)
+ * "src_len" == 2
+ * "dst_len" == 6
+ * ->
+ * Returned value == 6
+ * "dst" becomes \xE3\x81\x82\xE3\x81\x84
+ * (note that "dst" is NOT null-terminated, like strncpy)
+ */
+void utf32_to_utf8(const char32_t* src, size_t src_len, char* dst);
+
+/**
+ * Returns the unicode value at "index".
+ * Returns -1 when the index is invalid (equals to or more than "src_len").
+ * If returned value is positive, it is able to be converted to char32_t, which
+ * is unsigned. Then, if "next_index" is not NULL, the next index to be used is
+ * stored in "next_index". "next_index" can be NULL.
+ */
+int32_t utf32_from_utf8_at(const char *src, size_t src_len, size_t index, size_t *next_index);
+
+
+/**
+ * Returns the UTF-8 length of UTF-16 string "src".
+ */
+ssize_t utf16_to_utf8_length(const char16_t *src, size_t src_len);
+
+/**
+ * Converts a UTF-16 string to UTF-8. The destination buffer must be large
+ * enough to fit the UTF-16 as measured by utf16_to_utf8_length with an added
+ * NULL terminator.
+ */
+void utf16_to_utf8(const char16_t* src, size_t src_len, char* dst);
+
+/**
+ * Returns the length of "src" when "src" is valid UTF-8 string.
+ * Returns 0 if src is NULL or 0-length string. Returns -1 when the source
+ * is an invalid string.
+ *
+ * This function should be used to determine whether "src" is valid UTF-8
+ * characters with valid unicode codepoints. "src" must be null-terminated.
+ *
+ * If you are going to use other utf8_to_... functions defined in this header
+ * with string which may not be valid UTF-8 with valid codepoint (form 0 to
+ * 0x10FFFF), you should use this function before calling others, since the
+ * other functions do not check whether the string is valid UTF-8 or not.
+ *
+ * If you do not care whether "src" is valid UTF-8 or not, you should use
+ * strlen() as usual, which should be much faster.
+ */
+ssize_t utf8_length(const char *src);
+
+/**
+ * Measure the length of a UTF-32 string.
+ */
+size_t utf8_to_utf32_length(const char *src, size_t src_len);
+
+/**
+ * Stores a UTF-32 string converted from "src" in "dst". "dst" must be large
+ * enough to store the entire converted string as measured by
+ * utf8_to_utf32_length plus space for a NULL terminator.
+ */
+void utf8_to_utf32(const char* src, size_t src_len, char32_t* dst);
+
+/**
+ * Returns the UTF-16 length of UTF-8 string "src".
+ */
+ssize_t utf8_to_utf16_length(const uint8_t* src, size_t srcLen);
+
+/**
+ * Convert UTF-8 to UTF-16 including surrogate pairs.
+ * Returns a pointer to the end of the string (where a null terminator might go
+ * if you wanted to add one).
+ */
+char16_t* utf8_to_utf16_no_null_terminator(const uint8_t* src, size_t srcLen, char16_t* dst);
+
+/**
+ * Convert UTF-8 to UTF-16 including surrogate pairs. The destination buffer
+ * must be large enough to hold the result as measured by utf8_to_utf16_length
+ * plus an added NULL terminator.
+ */
+void utf8_to_utf16(const uint8_t* src, size_t srcLen, char16_t* dst);
+
+/**
+ * Like utf8_to_utf16_no_null_terminator, but you can supply a maximum length of the
+ * decoded string.  The decoded string will fill up to that length; if it is longer
+ * the returned pointer will be to the character after dstLen.
+ */
+char16_t* utf8_to_utf16_n(const uint8_t* src, size_t srcLen, char16_t* dst, size_t dstLen);
+
+}
+
+#endif
diff --git a/package/utils/adbd/src/include/utils/Vector.h b/package/utils/adbd/src/include/utils/Vector.h
new file mode 100644
index 0000000..ed7b725
--- /dev/null
+++ b/package/utils/adbd/src/include/utils/Vector.h
@@ -0,0 +1,423 @@
+/*
+ * Copyright (C) 2005 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 ANDROID_VECTOR_H
+#define ANDROID_VECTOR_H
+
+#include <new>
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <cutils/log.h>
+
+#include <utils/VectorImpl.h>
+#include <utils/TypeHelpers.h>
+
+// ---------------------------------------------------------------------------
+
+namespace android {
+
+template <typename TYPE>
+class SortedVector;
+
+/*!
+ * The main templated vector class ensuring type safety
+ * while making use of VectorImpl.
+ * This is the class users want to use.
+ */
+
+template <class TYPE>
+class Vector : private VectorImpl
+{
+public:
+            typedef TYPE    value_type;
+    
+    /*! 
+     * Constructors and destructors
+     */
+    
+                            Vector();
+                            Vector(const Vector<TYPE>& rhs);
+    explicit                Vector(const SortedVector<TYPE>& rhs);
+    virtual                 ~Vector();
+
+    /*! copy operator */
+            const Vector<TYPE>&     operator = (const Vector<TYPE>& rhs) const;
+            Vector<TYPE>&           operator = (const Vector<TYPE>& rhs);    
+
+            const Vector<TYPE>&     operator = (const SortedVector<TYPE>& rhs) const;
+            Vector<TYPE>&           operator = (const SortedVector<TYPE>& rhs);
+
+            /*
+     * empty the vector
+     */
+
+    inline  void            clear()             { VectorImpl::clear(); }
+
+    /*! 
+     * vector stats
+     */
+
+    //! returns number of items in the vector
+    inline  size_t          size() const                { return VectorImpl::size(); }
+    //! returns whether or not the vector is empty
+    inline  bool            isEmpty() const             { return VectorImpl::isEmpty(); }
+    //! returns how many items can be stored without reallocating the backing store
+    inline  size_t          capacity() const            { return VectorImpl::capacity(); }
+    //! sets the capacity. capacity can never be reduced less than size()
+    inline  ssize_t         setCapacity(size_t size)    { return VectorImpl::setCapacity(size); }
+
+    /*!
+     * set the size of the vector. items are appended with the default
+     * constructor, or removed from the end as needed.
+     */
+    inline  ssize_t         resize(size_t size)         { return VectorImpl::resize(size); }
+
+    /*!
+     * C-style array access
+     */
+     
+    //! read-only C-style access 
+    inline  const TYPE*     array() const;
+    //! read-write C-style access
+            TYPE*           editArray();
+    
+    /*! 
+     * accessors
+     */
+
+    //! read-only access to an item at a given index
+    inline  const TYPE&     operator [] (size_t index) const;
+    //! alternate name for operator []
+    inline  const TYPE&     itemAt(size_t index) const;
+    //! stack-usage of the vector. returns the top of the stack (last element)
+            const TYPE&     top() const;
+
+    /*!
+     * modifying the array
+     */
+
+    //! copy-on write support, grants write access to an item
+            TYPE&           editItemAt(size_t index);
+    //! grants right access to the top of the stack (last element)
+            TYPE&           editTop();
+
+            /*! 
+             * append/insert another vector
+             */
+            
+    //! insert another vector at a given index
+            ssize_t         insertVectorAt(const Vector<TYPE>& vector, size_t index);
+
+    //! append another vector at the end of this one
+            ssize_t         appendVector(const Vector<TYPE>& vector);
+
+
+    //! insert an array at a given index
+            ssize_t         insertArrayAt(const TYPE* array, size_t index, size_t length);
+
+    //! append an array at the end of this vector
+            ssize_t         appendArray(const TYPE* array, size_t length);
+
+            /*! 
+             * add/insert/replace items
+             */
+             
+    //! insert one or several items initialized with their default constructor
+    inline  ssize_t         insertAt(size_t index, size_t numItems = 1);
+    //! insert one or several items initialized from a prototype item
+            ssize_t         insertAt(const TYPE& prototype_item, size_t index, size_t numItems = 1);
+    //! pop the top of the stack (removes the last element). No-op if the stack's empty
+    inline  void            pop();
+    //! pushes an item initialized with its default constructor
+    inline  void            push();
+    //! pushes an item on the top of the stack
+            void            push(const TYPE& item);
+    //! same as push() but returns the index the item was added at (or an error)
+    inline  ssize_t         add();
+    //! same as push() but returns the index the item was added at (or an error)
+            ssize_t         add(const TYPE& item);            
+    //! replace an item with a new one initialized with its default constructor
+    inline  ssize_t         replaceAt(size_t index);
+    //! replace an item with a new one
+            ssize_t         replaceAt(const TYPE& item, size_t index);
+
+    /*!
+     * remove items
+     */
+
+    //! remove several items
+    inline  ssize_t         removeItemsAt(size_t index, size_t count = 1);
+    //! remove one item
+    inline  ssize_t         removeAt(size_t index)  { return removeItemsAt(index); }
+
+    /*!
+     * sort (stable) the array
+     */
+     
+     typedef int (*compar_t)(const TYPE* lhs, const TYPE* rhs);
+     typedef int (*compar_r_t)(const TYPE* lhs, const TYPE* rhs, void* state);
+     
+     inline status_t        sort(compar_t cmp);
+     inline status_t        sort(compar_r_t cmp, void* state);
+
+     // for debugging only
+     inline size_t getItemSize() const { return itemSize(); }
+
+
+     /*
+      * these inlines add some level of compatibility with STL. eventually
+      * we should probably turn things around.
+      */
+     typedef TYPE* iterator;
+     typedef TYPE const* const_iterator;
+
+     inline iterator begin() { return editArray(); }
+     inline iterator end()   { return editArray() + size(); }
+     inline const_iterator begin() const { return array(); }
+     inline const_iterator end() const   { return array() + size(); }
+     inline void reserve(size_t n) { setCapacity(n); }
+     inline bool empty() const{ return isEmpty(); }
+     inline void push_back(const TYPE& item)  { insertAt(item, size(), 1); }
+     inline void push_front(const TYPE& item) { insertAt(item, 0, 1); }
+     inline iterator erase(iterator pos) {
+         ssize_t index = removeItemsAt(pos-array());
+         return begin() + index;
+     }
+
+protected:
+    virtual void    do_construct(void* storage, size_t num) const;
+    virtual void    do_destroy(void* storage, size_t num) const;
+    virtual void    do_copy(void* dest, const void* from, size_t num) const;
+    virtual void    do_splat(void* dest, const void* item, size_t num) const;
+    virtual void    do_move_forward(void* dest, const void* from, size_t num) const;
+    virtual void    do_move_backward(void* dest, const void* from, size_t num) const;
+};
+
+// Vector<T> can be trivially moved using memcpy() because moving does not
+// require any change to the underlying SharedBuffer contents or reference count.
+template<typename T> struct trait_trivial_move<Vector<T> > { enum { value = true }; };
+
+// ---------------------------------------------------------------------------
+// No user serviceable parts from here...
+// ---------------------------------------------------------------------------
+
+template<class TYPE> inline
+Vector<TYPE>::Vector()
+    : VectorImpl(sizeof(TYPE),
+                ((traits<TYPE>::has_trivial_ctor   ? HAS_TRIVIAL_CTOR   : 0)
+                |(traits<TYPE>::has_trivial_dtor   ? HAS_TRIVIAL_DTOR   : 0)
+                |(traits<TYPE>::has_trivial_copy   ? HAS_TRIVIAL_COPY   : 0))
+                )
+{
+}
+
+template<class TYPE> inline
+Vector<TYPE>::Vector(const Vector<TYPE>& rhs)
+    : VectorImpl(rhs) {
+}
+
+template<class TYPE> inline
+Vector<TYPE>::Vector(const SortedVector<TYPE>& rhs)
+    : VectorImpl(static_cast<const VectorImpl&>(rhs)) {
+}
+
+template<class TYPE> inline
+Vector<TYPE>::~Vector() {
+    finish_vector();
+}
+
+template<class TYPE> inline
+Vector<TYPE>& Vector<TYPE>::operator = (const Vector<TYPE>& rhs) {
+    VectorImpl::operator = (rhs);
+    return *this; 
+}
+
+template<class TYPE> inline
+const Vector<TYPE>& Vector<TYPE>::operator = (const Vector<TYPE>& rhs) const {
+    VectorImpl::operator = (static_cast<const VectorImpl&>(rhs));
+    return *this;
+}
+
+template<class TYPE> inline
+Vector<TYPE>& Vector<TYPE>::operator = (const SortedVector<TYPE>& rhs) {
+    VectorImpl::operator = (static_cast<const VectorImpl&>(rhs));
+    return *this;
+}
+
+template<class TYPE> inline
+const Vector<TYPE>& Vector<TYPE>::operator = (const SortedVector<TYPE>& rhs) const {
+    VectorImpl::operator = (rhs);
+    return *this; 
+}
+
+template<class TYPE> inline
+const TYPE* Vector<TYPE>::array() const {
+    return static_cast<const TYPE *>(arrayImpl());
+}
+
+template<class TYPE> inline
+TYPE* Vector<TYPE>::editArray() {
+    return static_cast<TYPE *>(editArrayImpl());
+}
+
+
+template<class TYPE> inline
+const TYPE& Vector<TYPE>::operator[](size_t index) const {
+    LOG_FATAL_IF(index>=size(),
+            "%s: index=%u out of range (%u)", __PRETTY_FUNCTION__,
+            int(index), int(size()));
+    return *(array() + index);
+}
+
+template<class TYPE> inline
+const TYPE& Vector<TYPE>::itemAt(size_t index) const {
+    return operator[](index);
+}
+
+template<class TYPE> inline
+const TYPE& Vector<TYPE>::top() const {
+    return *(array() + size() - 1);
+}
+
+template<class TYPE> inline
+TYPE& Vector<TYPE>::editItemAt(size_t index) {
+    return *( static_cast<TYPE *>(editItemLocation(index)) );
+}
+
+template<class TYPE> inline
+TYPE& Vector<TYPE>::editTop() {
+    return *( static_cast<TYPE *>(editItemLocation(size()-1)) );
+}
+
+template<class TYPE> inline
+ssize_t Vector<TYPE>::insertVectorAt(const Vector<TYPE>& vector, size_t index) {
+    return VectorImpl::insertVectorAt(reinterpret_cast<const VectorImpl&>(vector), index);
+}
+
+template<class TYPE> inline
+ssize_t Vector<TYPE>::appendVector(const Vector<TYPE>& vector) {
+    return VectorImpl::appendVector(reinterpret_cast<const VectorImpl&>(vector));
+}
+
+template<class TYPE> inline
+ssize_t Vector<TYPE>::insertArrayAt(const TYPE* array, size_t index, size_t length) {
+    return VectorImpl::insertArrayAt(array, index, length);
+}
+
+template<class TYPE> inline
+ssize_t Vector<TYPE>::appendArray(const TYPE* array, size_t length) {
+    return VectorImpl::appendArray(array, length);
+}
+
+template<class TYPE> inline
+ssize_t Vector<TYPE>::insertAt(const TYPE& item, size_t index, size_t numItems) {
+    return VectorImpl::insertAt(&item, index, numItems);
+}
+
+template<class TYPE> inline
+void Vector<TYPE>::push(const TYPE& item) {
+    return VectorImpl::push(&item);
+}
+
+template<class TYPE> inline
+ssize_t Vector<TYPE>::add(const TYPE& item) {
+    return VectorImpl::add(&item);
+}
+
+template<class TYPE> inline
+ssize_t Vector<TYPE>::replaceAt(const TYPE& item, size_t index) {
+    return VectorImpl::replaceAt(&item, index);
+}
+
+template<class TYPE> inline
+ssize_t Vector<TYPE>::insertAt(size_t index, size_t numItems) {
+    return VectorImpl::insertAt(index, numItems);
+}
+
+template<class TYPE> inline
+void Vector<TYPE>::pop() {
+    VectorImpl::pop();
+}
+
+template<class TYPE> inline
+void Vector<TYPE>::push() {
+    VectorImpl::push();
+}
+
+template<class TYPE> inline
+ssize_t Vector<TYPE>::add() {
+    return VectorImpl::add();
+}
+
+template<class TYPE> inline
+ssize_t Vector<TYPE>::replaceAt(size_t index) {
+    return VectorImpl::replaceAt(index);
+}
+
+template<class TYPE> inline
+ssize_t Vector<TYPE>::removeItemsAt(size_t index, size_t count) {
+    return VectorImpl::removeItemsAt(index, count);
+}
+
+template<class TYPE> inline
+status_t Vector<TYPE>::sort(Vector<TYPE>::compar_t cmp) {
+    return VectorImpl::sort((VectorImpl::compar_t)cmp);
+}
+
+template<class TYPE> inline
+status_t Vector<TYPE>::sort(Vector<TYPE>::compar_r_t cmp, void* state) {
+    return VectorImpl::sort((VectorImpl::compar_r_t)cmp, state);
+}
+
+// ---------------------------------------------------------------------------
+
+template<class TYPE>
+void Vector<TYPE>::do_construct(void* storage, size_t num) const {
+    construct_type( reinterpret_cast<TYPE*>(storage), num );
+}
+
+template<class TYPE>
+void Vector<TYPE>::do_destroy(void* storage, size_t num) const {
+    destroy_type( reinterpret_cast<TYPE*>(storage), num );
+}
+
+template<class TYPE>
+void Vector<TYPE>::do_copy(void* dest, const void* from, size_t num) const {
+    copy_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(from), num );
+}
+
+template<class TYPE>
+void Vector<TYPE>::do_splat(void* dest, const void* item, size_t num) const {
+    splat_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(item), num );
+}
+
+template<class TYPE>
+void Vector<TYPE>::do_move_forward(void* dest, const void* from, size_t num) const {
+    move_forward_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(from), num );
+}
+
+template<class TYPE>
+void Vector<TYPE>::do_move_backward(void* dest, const void* from, size_t num) const {
+    move_backward_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(from), num );
+}
+
+}; // namespace android
+
+
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_VECTOR_H
diff --git a/package/utils/adbd/src/include/utils/VectorImpl.h b/package/utils/adbd/src/include/utils/VectorImpl.h
new file mode 100644
index 0000000..21ad71c
--- /dev/null
+++ b/package/utils/adbd/src/include/utils/VectorImpl.h
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2005 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 ANDROID_VECTOR_IMPL_H
+#define ANDROID_VECTOR_IMPL_H
+
+#include <assert.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <utils/Errors.h>
+
+// ---------------------------------------------------------------------------
+// No user serviceable parts in here...
+// ---------------------------------------------------------------------------
+
+namespace android {
+
+/*!
+ * Implementation of the guts of the vector<> class
+ * this ensures backward binary compatibility and
+ * reduces code size.
+ * For performance reasons, we expose mStorage and mCount
+ * so these fields are set in stone.
+ *
+ */
+
+class VectorImpl
+{
+public:
+    enum { // flags passed to the ctor
+        HAS_TRIVIAL_CTOR    = 0x00000001,
+        HAS_TRIVIAL_DTOR    = 0x00000002,
+        HAS_TRIVIAL_COPY    = 0x00000004,
+    };
+
+                            VectorImpl(size_t itemSize, uint32_t flags);
+                            VectorImpl(const VectorImpl& rhs);
+    virtual                 ~VectorImpl();
+
+    /*! must be called from subclasses destructor */
+            void            finish_vector();
+
+            VectorImpl&     operator = (const VectorImpl& rhs);    
+            
+    /*! C-style array access */
+    inline  const void*     arrayImpl() const       { return mStorage; }
+            void*           editArrayImpl();
+            
+    /*! vector stats */
+    inline  size_t          size() const        { return mCount; }
+    inline  bool            isEmpty() const     { return mCount == 0; }
+            size_t          capacity() const;
+            ssize_t         setCapacity(size_t size);
+            ssize_t         resize(size_t size);
+
+            /*! append/insert another vector or array */
+            ssize_t         insertVectorAt(const VectorImpl& vector, size_t index);
+            ssize_t         appendVector(const VectorImpl& vector);
+            ssize_t         insertArrayAt(const void* array, size_t index, size_t length);
+            ssize_t         appendArray(const void* array, size_t length);
+            
+            /*! add/insert/replace items */
+            ssize_t         insertAt(size_t where, size_t numItems = 1);
+            ssize_t         insertAt(const void* item, size_t where, size_t numItems = 1);
+            void            pop();
+            void            push();
+            void            push(const void* item);
+            ssize_t         add();
+            ssize_t         add(const void* item);
+            ssize_t         replaceAt(size_t index);
+            ssize_t         replaceAt(const void* item, size_t index);
+
+            /*! remove items */
+            ssize_t         removeItemsAt(size_t index, size_t count = 1);
+            void            clear();
+
+            const void*     itemLocation(size_t index) const;
+            void*           editItemLocation(size_t index);
+
+            typedef int (*compar_t)(const void* lhs, const void* rhs);
+            typedef int (*compar_r_t)(const void* lhs, const void* rhs, void* state);
+            status_t        sort(compar_t cmp);
+            status_t        sort(compar_r_t cmp, void* state);
+
+protected:
+            size_t          itemSize() const;
+            void            release_storage();
+
+    virtual void            do_construct(void* storage, size_t num) const = 0;
+    virtual void            do_destroy(void* storage, size_t num) const = 0;
+    virtual void            do_copy(void* dest, const void* from, size_t num) const = 0;
+    virtual void            do_splat(void* dest, const void* item, size_t num) const = 0;
+    virtual void            do_move_forward(void* dest, const void* from, size_t num) const = 0;
+    virtual void            do_move_backward(void* dest, const void* from, size_t num) const = 0;
+    
+private:
+        void* _grow(size_t where, size_t amount);
+        void  _shrink(size_t where, size_t amount);
+
+        inline void _do_construct(void* storage, size_t num) const;
+        inline void _do_destroy(void* storage, size_t num) const;
+        inline void _do_copy(void* dest, const void* from, size_t num) const;
+        inline void _do_splat(void* dest, const void* item, size_t num) const;
+        inline void _do_move_forward(void* dest, const void* from, size_t num) const;
+        inline void _do_move_backward(void* dest, const void* from, size_t num) const;
+
+            // These 2 fields are exposed in the inlines below,
+            // so they're set in stone.
+            void *      mStorage;   // base address of the vector
+            size_t      mCount;     // number of items
+
+    const   uint32_t    mFlags;
+    const   size_t      mItemSize;
+};
+
+
+
+class SortedVectorImpl : public VectorImpl
+{
+public:
+                            SortedVectorImpl(size_t itemSize, uint32_t flags);
+                            SortedVectorImpl(const VectorImpl& rhs);
+    virtual                 ~SortedVectorImpl();
+    
+    SortedVectorImpl&     operator = (const SortedVectorImpl& rhs);    
+
+    //! finds the index of an item
+            ssize_t         indexOf(const void* item) const;
+
+    //! finds where this item should be inserted
+            size_t          orderOf(const void* item) const;
+
+    //! add an item in the right place (or replaces it if there is one)
+            ssize_t         add(const void* item);
+
+    //! merges a vector into this one
+            ssize_t         merge(const VectorImpl& vector);
+            ssize_t         merge(const SortedVectorImpl& vector);
+             
+    //! removes an item
+            ssize_t         remove(const void* item);
+        
+protected:
+    virtual int             do_compare(const void* lhs, const void* rhs) const = 0;
+
+private:
+            ssize_t         _indexOrderOf(const void* item, size_t* order = 0) const;
+
+            // these are made private, because they can't be used on a SortedVector
+            // (they don't have an implementation either)
+            ssize_t         add();
+            void            pop();
+            void            push();
+            void            push(const void* item);
+            ssize_t         insertVectorAt(const VectorImpl& vector, size_t index);
+            ssize_t         appendVector(const VectorImpl& vector);
+            ssize_t         insertArrayAt(const void* array, size_t index, size_t length);
+            ssize_t         appendArray(const void* array, size_t length);
+            ssize_t         insertAt(size_t where, size_t numItems = 1);
+            ssize_t         insertAt(const void* item, size_t where, size_t numItems = 1);
+            ssize_t         replaceAt(size_t index);
+            ssize_t         replaceAt(const void* item, size_t index);
+};
+
+}; // namespace android
+
+
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_VECTOR_IMPL_H
diff --git a/package/utils/adbd/src/include/utils/ashmem.h b/package/utils/adbd/src/include/utils/ashmem.h
new file mode 100644
index 0000000..0854775
--- /dev/null
+++ b/package/utils/adbd/src/include/utils/ashmem.h
@@ -0,0 +1,41 @@
+/* utils/ashmem.h
+ **
+ ** Copyright 2008 The Android Open Source Project
+ **
+ ** This file is dual licensed.  It may be redistributed and/or modified
+ ** under the terms of the Apache 2.0 License OR version 2 of the GNU
+ ** General Public License.
+ */
+
+#ifndef _UTILS_ASHMEM_H
+#define _UTILS_ASHMEM_H
+
+#include <linux/limits.h>
+#include <linux/ioctl.h>
+
+#define ASHMEM_NAME_LEN		256
+
+#define ASHMEM_NAME_DEF		"dev/ashmem"
+
+/* Return values from ASHMEM_PIN: Was the mapping purged while unpinned? */
+#define ASHMEM_NOT_REAPED	0
+#define ASHMEM_WAS_REAPED	1
+
+/* Return values from ASHMEM_UNPIN: Is the mapping now pinned or unpinned? */
+#define ASHMEM_NOW_UNPINNED	0
+#define ASHMEM_NOW_PINNED	1
+
+#define __ASHMEMIOC		0x77
+
+#define ASHMEM_SET_NAME		_IOW(__ASHMEMIOC, 1, char[ASHMEM_NAME_LEN])
+#define ASHMEM_GET_NAME		_IOR(__ASHMEMIOC, 2, char[ASHMEM_NAME_LEN])
+#define ASHMEM_SET_SIZE		_IOW(__ASHMEMIOC, 3, size_t)
+#define ASHMEM_GET_SIZE		_IO(__ASHMEMIOC, 4)
+#define ASHMEM_SET_PROT_MASK	_IOW(__ASHMEMIOC, 5, unsigned long)
+#define ASHMEM_GET_PROT_MASK	_IO(__ASHMEMIOC, 6)
+#define ASHMEM_PIN		_IO(__ASHMEMIOC, 7)
+#define ASHMEM_UNPIN		_IO(__ASHMEMIOC, 8)
+#define ASHMEM_ISPINNED		_IO(__ASHMEMIOC, 9)
+#define ASHMEM_PURGE_ALL_CACHES	_IO(__ASHMEMIOC, 10)
+
+#endif	/* _UTILS_ASHMEM_H */
diff --git a/package/utils/adbd/src/include/utils/misc.h b/package/utils/adbd/src/include/utils/misc.h
new file mode 100644
index 0000000..6cccec3
--- /dev/null
+++ b/package/utils/adbd/src/include/utils/misc.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+//
+// Handy utility functions and portability code.
+//
+#ifndef _LIBS_UTILS_MISC_H
+#define _LIBS_UTILS_MISC_H
+
+#include <utils/Endian.h>
+
+/* get #of elements in a static array */
+#ifndef NELEM
+# define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0])))
+#endif
+
+namespace android {
+
+typedef void (*sysprop_change_callback)(void);
+void add_sysprop_change_callback(sysprop_change_callback cb, int priority);
+void report_sysprop_change();
+
+}; // namespace android
+
+#endif // _LIBS_UTILS_MISC_H
diff --git a/package/utils/adbd/src/include/utils/threads.h b/package/utils/adbd/src/include/utils/threads.h
new file mode 100644
index 0000000..9de3382
--- /dev/null
+++ b/package/utils/adbd/src/include/utils/threads.h
@@ -0,0 +1,38 @@
+/*
+ * 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 _LIBS_UTILS_THREADS_H
+#define _LIBS_UTILS_THREADS_H
+
+/*
+ * Please, DO NOT USE!
+ *
+ * This file is here only for legacy reasons. Instead, include directly
+ * the headers you need below.
+ *
+ */
+
+#include <utils/AndroidThreads.h>
+
+#ifdef __cplusplus
+#include <utils/Condition.h>
+#include <utils/Errors.h>
+#include <utils/Mutex.h>
+#include <utils/RWLock.h>
+#include <utils/Thread.h>
+#endif
+
+#endif // _LIBS_UTILS_THREADS_H
diff --git a/package/utils/adbd/src/include/ziparchive/zip_archive.h b/package/utils/adbd/src/include/ziparchive/zip_archive.h
new file mode 100644
index 0000000..0fa21cc
--- /dev/null
+++ b/package/utils/adbd/src/include/ziparchive/zip_archive.h
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+/*
+ * Read-only access to Zip archives, with minimal heap allocation.
+ */
+#ifndef LIBZIPARCHIVE_ZIPARCHIVE_H_
+#define LIBZIPARCHIVE_ZIPARCHIVE_H_
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <utils/Compat.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/* Zip compression methods we support */
+enum {
+  kCompressStored     = 0,        // no compression
+  kCompressDeflated   = 8,        // standard deflate
+};
+
+struct ZipEntryName {
+  const char* name;
+  uint16_t name_length;
+};
+
+/*
+ * Represents information about a zip entry in a zip file.
+ */
+struct ZipEntry {
+  // Compression method: One of kCompressStored or
+  // kCompressDeflated.
+  uint16_t method;
+
+  // Modification time. The zipfile format specifies
+  // that the first two little endian bytes contain the time
+  // and the last two little endian bytes contain the date.
+  uint32_t mod_time;
+
+  // 1 if this entry contains a data descriptor segment, 0
+  // otherwise.
+  uint8_t has_data_descriptor;
+
+  // Crc32 value of this ZipEntry. This information might
+  // either be stored in the local file header or in a special
+  // Data descriptor footer at the end of the file entry.
+  uint32_t crc32;
+
+  // Compressed length of this ZipEntry. Might be present
+  // either in the local file header or in the data descriptor
+  // footer.
+  uint32_t compressed_length;
+
+  // Uncompressed length of this ZipEntry. Might be present
+  // either in the local file header or in the data descriptor
+  // footer.
+  uint32_t uncompressed_length;
+
+  // The offset to the start of data for this ZipEntry.
+  off64_t offset;
+};
+
+typedef void* ZipArchiveHandle;
+
+/*
+ * Open a Zip archive, and sets handle to the value of the opaque
+ * handle for the file. This handle must be released by calling
+ * CloseArchive with this handle.
+ *
+ * Returns 0 on success, and negative values on failure.
+ */
+int32_t OpenArchive(const char* fileName, ZipArchiveHandle* handle);
+
+/*
+ * Like OpenArchive, but takes a file descriptor open for reading
+ * at the start of the file.  The descriptor must be mappable (this does
+ * not allow access to a stream).
+ *
+ * Sets handle to the value of the opaque handle for this file descriptor.
+ * This handle must be released by calling CloseArchive with this handle.
+ *
+ * This function maps and scans the central directory and builds a table
+ * of entries for future lookups.
+ *
+ * "debugFileName" will appear in error messages, but is not otherwise used.
+ *
+ * Returns 0 on success, and negative values on failure.
+ */
+int32_t OpenArchiveFd(const int fd, const char* debugFileName,
+                      ZipArchiveHandle *handle);
+
+/*
+ * Close archive, releasing resources associated with it. This will
+ * unmap the central directory of the zipfile and free all internal
+ * data structures associated with the file. It is an error to use
+ * this handle for any further operations without an intervening
+ * call to one of the OpenArchive variants.
+ */
+void CloseArchive(ZipArchiveHandle handle);
+
+/*
+ * Find an entry in the Zip archive, by name. |entryName| must be a null
+ * terminated string, and |data| must point to a writeable memory location.
+ *
+ * Returns 0 if an entry is found, and populates |data| with information
+ * about this entry. Returns negative values otherwise.
+ *
+ * It's important to note that |data->crc32|, |data->compLen| and
+ * |data->uncompLen| might be set to values from the central directory
+ * if this file entry contains a data descriptor footer. To verify crc32s
+ * and length, a call to VerifyCrcAndLengths must be made after entry data
+ * has been processed.
+ */
+int32_t FindEntry(const ZipArchiveHandle handle, const char* entryName,
+                  ZipEntry* data);
+
+/*
+ * Start iterating over all entries of a zip file. The order of iteration
+ * is not guaranteed to be the same as the order of elements
+ * in the central directory but is stable for a given zip file. |cookie|
+ * must point to a writeable memory location, and will be set to the value
+ * of an opaque cookie which can be used to make one or more calls to
+ * Next.
+ *
+ * This method also accepts an optional prefix to restrict iteration to
+ * entry names that start with |prefix|.
+ *
+ * Returns 0 on success and negative values on failure.
+ */
+int32_t StartIteration(ZipArchiveHandle handle, void** cookie_ptr,
+                       const char* prefix);
+
+/*
+ * Advance to the next element in the zipfile in iteration order.
+ *
+ * Returns 0 on success, -1 if there are no more elements in this
+ * archive and lower negative values on failure.
+ */
+int32_t Next(void* cookie, ZipEntry* data, ZipEntryName *name);
+
+/*
+ * Uncompress and write an entry to an open file identified by |fd|.
+ * |entry->uncompressed_length| bytes will be written to the file at
+ * its current offset, and the file will be truncated at the end of
+ * the uncompressed data.
+ *
+ * Returns 0 on success and negative values on failure.
+ */
+int32_t ExtractEntryToFile(ZipArchiveHandle handle, ZipEntry* entry, int fd);
+
+/**
+ * Uncompress a given zip entry to the memory region at |begin| and of
+ * size |size|. This size is expected to be the same as the *declared*
+ * uncompressed length of the zip entry. It is an error if the *actual*
+ * number of uncompressed bytes differs from this number.
+ *
+ * Returns 0 on success and negative values on failure.
+ */
+int32_t ExtractToMemory(ZipArchiveHandle handle, ZipEntry* entry,
+                        uint8_t* begin, uint32_t size);
+
+int GetFileDescriptor(const ZipArchiveHandle handle);
+
+const char* ErrorCodeString(int32_t error_code);
+
+#ifdef __cplusplus
+}
+#endif
+#endif  // LIBZIPARCHIVE_ZIPARCHIVE_H_
diff --git a/package/utils/adbd/src/include/zipfile/zipfile.h b/package/utils/adbd/src/include/zipfile/zipfile.h
new file mode 100644
index 0000000..0ae4ee4
--- /dev/null
+++ b/package/utils/adbd/src/include/zipfile/zipfile.h
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+#ifndef _ZIPFILE_ZIPFILE_H
+#define _ZIPFILE_ZIPFILE_H
+
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void* zipfile_t;
+typedef void* zipentry_t;
+
+// Provide a buffer.  Returns NULL on failure.
+zipfile_t init_zipfile(const void* data, size_t size);
+
+// Release the zipfile resources.
+void release_zipfile(zipfile_t file);
+
+// Get a named entry object.  Returns NULL if it doesn't exist
+// or if we won't be able to decompress it.  The zipentry_t is
+// freed by release_zipfile()
+zipentry_t lookup_zipentry(zipfile_t file, const char* entryName);
+
+// Return the size of the entry.
+size_t get_zipentry_size(zipentry_t entry);
+
+// return the filename of this entry, you own the memory returned
+char* get_zipentry_name(zipentry_t entry);
+
+// The buffer must be 1.001 times the buffer size returned
+// by get_zipentry_size.  Returns nonzero on failure.
+int decompress_zipentry(zipentry_t entry, void* buf, int bufsize);
+
+// iterate through the entries in the zip file.  pass a pointer to
+// a void* initialized to NULL to start.  Returns NULL when done
+zipentry_t iterate_zipfile(zipfile_t file, void** cookie);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _ZIPFILE_ZIPFILE_H
diff --git a/package/utils/adbd/src/libcutils/Android.mk b/package/utils/adbd/src/libcutils/Android.mk
new file mode 100644
index 0000000..933a77b
--- /dev/null
+++ b/package/utils/adbd/src/libcutils/Android.mk
@@ -0,0 +1,183 @@
+#
+# 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.
+#
+LOCAL_PATH := $(my-dir)
+include $(CLEAR_VARS)
+
+ifeq ($(TARGET_CPU_SMP),true)
+    targetSmpFlag := -DANDROID_SMP=1
+else
+    targetSmpFlag := -DANDROID_SMP=0
+endif
+hostSmpFlag := -DANDROID_SMP=0
+
+commonSources := \
+	hashmap.c \
+	atomic.c.arm \
+	native_handle.c \
+	config_utils.c \
+	cpu_info.c \
+	load_file.c \
+	open_memstream.c \
+	strdup16to8.c \
+	strdup8to16.c \
+	record_stream.c \
+	process_name.c \
+	threads.c \
+	sched_policy.c \
+	iosched_policy.c \
+	str_parms.c \
+
+# some files must not be compiled when building against Mingw
+# they correspond to features not used by our host development tools
+# which are also hard or even impossible to port to native Win32
+WINDOWS_HOST_ONLY :=
+ifeq ($(HOST_OS),windows)
+    ifeq ($(strip $(USE_CYGWIN)),)
+        WINDOWS_HOST_ONLY := 1
+    endif
+endif
+# USE_MINGW is defined when we build against Mingw on Linux
+ifneq ($(strip $(USE_MINGW)),)
+    WINDOWS_HOST_ONLY := 1
+endif
+
+ifneq ($(WINDOWS_HOST_ONLY),1)
+    commonSources += \
+        fs.c \
+        multiuser.c \
+        socket_inaddr_any_server.c \
+        socket_local_client.c \
+        socket_local_server.c \
+        socket_loopback_client.c \
+        socket_loopback_server.c \
+        socket_network_client.c \
+        sockets.c \
+
+    commonHostSources += \
+        ashmem-host.c
+
+endif
+
+
+# Static library for host
+# ========================================================
+LOCAL_MODULE := libcutils
+LOCAL_SRC_FILES := $(commonSources) $(commonHostSources) dlmalloc_stubs.c
+LOCAL_STATIC_LIBRARIES := liblog
+LOCAL_CFLAGS += $(hostSmpFlag)
+ifneq ($(HOST_OS),windows)
+LOCAL_CFLAGS += -Werror
+endif
+LOCAL_MULTILIB := both
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+include $(BUILD_HOST_STATIC_LIBRARY)
+
+
+# Static library for host, 64-bit
+# ========================================================
+include $(CLEAR_VARS)
+LOCAL_MODULE := lib64cutils
+LOCAL_SRC_FILES := $(commonSources) $(commonHostSources) dlmalloc_stubs.c
+LOCAL_STATIC_LIBRARIES := lib64log
+LOCAL_CFLAGS += $(hostSmpFlag) -m64
+ifneq ($(HOST_OS),windows)
+LOCAL_CFLAGS += -Werror
+endif
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+include $(BUILD_HOST_STATIC_LIBRARY)
+
+# Tests for host
+# ========================================================
+include $(CLEAR_VARS)
+LOCAL_MODULE := tst_str_parms
+LOCAL_CFLAGS += -DTEST_STR_PARMS
+ifneq ($(HOST_OS),windows)
+LOCAL_CFLAGS += -Werror
+endif
+LOCAL_SRC_FILES := str_parms.c hashmap.c memory.c
+LOCAL_STATIC_LIBRARIES := liblog
+LOCAL_MODULE_TAGS := optional
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+include $(BUILD_HOST_EXECUTABLE)
+
+
+# Shared and static library for target
+# ========================================================
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libcutils
+LOCAL_SRC_FILES := $(commonSources) \
+        android_reboot.c \
+        ashmem-dev.c \
+        debugger.c \
+        klog.c \
+        memory.c \
+        partition_utils.c \
+        properties.c \
+        qtaguid.c \
+        trace.c \
+        uevent.c \
+
+LOCAL_SRC_FILES_arm += \
+        arch-arm/memset32.S \
+
+LOCAL_SRC_FILES_arm64 += \
+        arch-arm64/android_memset.S \
+
+LOCAL_SRC_FILES_mips += \
+        arch-mips/android_memset.c \
+
+LOCAL_SRC_FILES_x86 += \
+        arch-x86/android_memset16.S \
+        arch-x86/android_memset32.S \
+
+LOCAL_SRC_FILES_x86_64 += \
+        arch-x86_64/android_memset16_SSE2-atom.S \
+        arch-x86_64/android_memset32_SSE2-atom.S \
+
+LOCAL_CFLAGS_arm += -DHAVE_MEMSET16 -DHAVE_MEMSET32
+LOCAL_CFLAGS_arm64 += -DHAVE_MEMSET16 -DHAVE_MEMSET32
+LOCAL_CFLAGS_mips += -DHAVE_MEMSET16 -DHAVE_MEMSET32
+LOCAL_CFLAGS_x86 += -DHAVE_MEMSET16 -DHAVE_MEMSET32
+LOCAL_CFLAGS_x86_64 += -DHAVE_MEMSET16 -DHAVE_MEMSET32
+
+LOCAL_C_INCLUDES := $(libcutils_c_includes)
+LOCAL_STATIC_LIBRARIES := liblog
+LOCAL_CFLAGS += $(targetSmpFlag) -Werror
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+include $(BUILD_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libcutils
+# TODO: remove liblog as whole static library, once we don't have prebuilt that requires
+# liblog symbols present in libcutils.
+LOCAL_WHOLE_STATIC_LIBRARIES := libcutils liblog
+LOCAL_SHARED_LIBRARIES := liblog
+LOCAL_CFLAGS += $(targetSmpFlag) -Werror
+LOCAL_C_INCLUDES := $(libcutils_c_includes)
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := tst_str_parms
+LOCAL_CFLAGS += -DTEST_STR_PARMS -Werror
+LOCAL_SRC_FILES := str_parms.c hashmap.c memory.c
+LOCAL_SHARED_LIBRARIES := liblog
+LOCAL_MODULE_TAGS := optional
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+include $(BUILD_EXECUTABLE)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/package/utils/adbd/src/libcutils/MODULE_LICENSE_APACHE2 b/package/utils/adbd/src/libcutils/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/package/utils/adbd/src/libcutils/MODULE_LICENSE_APACHE2
diff --git a/package/utils/adbd/src/libcutils/NOTICE b/package/utils/adbd/src/libcutils/NOTICE
new file mode 100644
index 0000000..c5b1efa
--- /dev/null
+++ b/package/utils/adbd/src/libcutils/NOTICE
@@ -0,0 +1,190 @@
+
+   Copyright (c) 2005-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.
+
+   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.
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
diff --git a/package/utils/adbd/src/libcutils/android_reboot.c b/package/utils/adbd/src/libcutils/android_reboot.c
new file mode 100644
index 0000000..5d98295
--- /dev/null
+++ b/package/utils/adbd/src/libcutils/android_reboot.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2011, 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 <unistd.h>
+#include <sys/reboot.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <cutils/android_reboot.h>
+
+#define UNUSED __attribute__((unused))
+
+/* Check to see if /proc/mounts contains any writeable filesystems
+ * backed by a block device.
+ * Return true if none found, else return false.
+ */
+static int remount_ro_done(void)
+{
+    FILE *f;
+    char mount_dev[256];
+    char mount_dir[256];
+    char mount_type[256];
+    char mount_opts[256];
+    int mount_freq;
+    int mount_passno;
+    int match;
+    int found_rw_fs = 0;
+
+    f = fopen("/proc/mounts", "r");
+    if (! f) {
+        /* If we can't read /proc/mounts, just give up */
+        return 1;
+    }
+
+    do {
+        match = fscanf(f, "%255s %255s %255s %255s %d %d\n",
+                       mount_dev, mount_dir, mount_type,
+                       mount_opts, &mount_freq, &mount_passno);
+        mount_dev[255] = 0;
+        mount_dir[255] = 0;
+        mount_type[255] = 0;
+        mount_opts[255] = 0;
+        if ((match == 6) && !strncmp(mount_dev, "/dev/block", 10) && strstr(mount_opts, "rw,")) {
+            found_rw_fs = 1;
+            break;
+        }
+    } while (match != EOF);
+
+    fclose(f);
+
+    return !found_rw_fs;
+}
+
+/* Remounting filesystems read-only is difficult when there are files
+ * opened for writing or pending deletes on the filesystem.  There is
+ * no way to force the remount with the mount(2) syscall.  The magic sysrq
+ * 'u' command does an emergency remount read-only on all writable filesystems
+ * that have a block device (i.e. not tmpfs filesystems) by calling
+ * emergency_remount(), which knows how to force the remount to read-only.
+ * Unfortunately, that is asynchronous, and just schedules the work and
+ * returns.  The best way to determine if it is done is to read /proc/mounts
+ * repeatedly until there are no more writable filesystems mounted on
+ * block devices.
+ */
+static void remount_ro(void)
+{
+    int fd, cnt = 0;
+
+    /* Trigger the remount of the filesystems as read-only,
+     * which also marks them clean.
+     */
+    fd = open("/proc/sysrq-trigger", O_WRONLY);
+    if (fd < 0) {
+        return;
+    }
+    write(fd, "u", 1);
+    close(fd);
+
+
+    /* Now poll /proc/mounts till it's done */
+    while (!remount_ro_done() && (cnt < 50)) {
+        usleep(100000);
+        cnt++;
+    }
+
+    return;
+}
+
+
+int android_reboot(int cmd, int flags UNUSED, char *arg)
+{
+    int ret;
+
+    sync();
+    remount_ro();
+
+    switch (cmd) {
+        case ANDROID_RB_RESTART:
+            ret = reboot(RB_AUTOBOOT);
+            break;
+
+        case ANDROID_RB_POWEROFF:
+            ret = reboot(RB_POWER_OFF);
+            break;
+
+        case ANDROID_RB_RESTART2:
+            ret = syscall(__NR_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
+                           LINUX_REBOOT_CMD_RESTART2, arg);
+            break;
+
+        default:
+            ret = -1;
+    }
+
+    return ret;
+}
+
diff --git a/package/utils/adbd/src/libcutils/arch-arm/memset32.S b/package/utils/adbd/src/libcutils/arch-arm/memset32.S
new file mode 100644
index 0000000..6efab9f
--- /dev/null
+++ b/package/utils/adbd/src/libcutils/arch-arm/memset32.S
@@ -0,0 +1,98 @@
+/*
+ * 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.
+ */
+/*
+ *  memset32.S
+ *
+ */
+
+    .text
+    .align
+
+    .global android_memset32
+    .type   android_memset32, %function
+    .global android_memset16
+    .type   android_memset16, %function
+
+        /*
+         * Optimized memset32 and memset16 for ARM.
+         *
+         * void android_memset16(uint16_t* dst, uint16_t value, size_t size);
+         * void android_memset32(uint32_t* dst, uint32_t value, size_t size);
+         *
+         */
+
+android_memset16:
+        .fnstart
+        cmp         r2, #1
+        bxle        lr
+
+        /* expand the data to 32 bits */
+        mov         r1, r1, lsl #16
+        orr         r1, r1, r1, lsr #16
+
+        /* align to 32 bits */
+        tst         r0, #2
+        strneh      r1, [r0], #2
+        subne       r2, r2, #2
+        .fnend
+
+android_memset32:
+        .fnstart
+        .cfi_startproc
+        str         lr, [sp, #-4]!
+        .cfi_def_cfa_offset 4
+        .cfi_rel_offset lr, 0
+
+        /* align the destination to a cache-line */
+        mov         r12, r1
+        mov         lr, r1
+        rsb         r3, r0, #0
+        ands        r3, r3, #0x1C
+        beq         .Laligned32
+        cmp         r3, r2
+        andhi       r3, r2, #0x1C
+        sub         r2, r2, r3
+
+        /* conditionally writes 0 to 7 words (length in r3) */
+        movs        r3, r3, lsl #28
+        stmcsia     r0!, {r1, lr}
+        stmcsia     r0!, {r1, lr}
+        stmmiia     r0!, {r1, lr}
+        movs        r3, r3, lsl #2
+        strcs       r1, [r0], #4
+
+.Laligned32:
+        mov         r3, r1
+1:      subs        r2, r2, #32
+        stmhsia     r0!, {r1,r3,r12,lr}
+        stmhsia     r0!, {r1,r3,r12,lr}
+        bhs         1b
+        add         r2, r2, #32
+
+        /* conditionally stores 0 to 30 bytes */
+        movs        r2, r2, lsl #28
+        stmcsia     r0!, {r1,r3,r12,lr}
+        stmmiia     r0!, {r1,lr}
+        movs        r2, r2, lsl #2
+        strcs       r1, [r0], #4
+        strmih      lr, [r0], #2
+
+        ldr         lr, [sp], #4
+        .cfi_def_cfa_offset 0
+        .cfi_restore lr
+        bx          lr
+        .cfi_endproc
+        .fnend
diff --git a/package/utils/adbd/src/libcutils/arch-arm64/android_memset.S b/package/utils/adbd/src/libcutils/arch-arm64/android_memset.S
new file mode 100644
index 0000000..9a83a68
--- /dev/null
+++ b/package/utils/adbd/src/libcutils/arch-arm64/android_memset.S
@@ -0,0 +1,211 @@
+/* Copyright (c) 2012, Linaro Limited
+   All rights reserved.
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are met:
+       * Redistributions of source code must retain the above copyright
+         notice, this list of conditions and the following disclaimer.
+       * Redistributions in binary form must reproduce the above copyright
+         notice, this list of conditions and the following disclaimer in the
+         documentation and/or other materials provided with the distribution.
+       * Neither the name of the Linaro nor the
+         names of its contributors may be used to endorse or promote products
+         derived from this software without specific prior written permission.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+   HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/* Assumptions:
+ *
+ * ARMv8-a, AArch64
+ * Unaligned accesses
+ *
+ */
+
+/* By default we assume that the DC instruction can be used to zero
+   data blocks more efficiently.  In some circumstances this might be
+   unsafe, for example in an asymmetric multiprocessor environment with
+   different DC clear lengths (neither the upper nor lower lengths are
+   safe to use). */
+
+#define dst  		x0
+#define count		x2
+#define tmp1		x3
+#define tmp1w		w3
+#define tmp2		x4
+#define tmp2w		w4
+#define zva_len_x	x5
+#define zva_len		w5
+#define zva_bits_x	x6
+
+#define A_l		x1
+#define A_lw		w1
+#define tmp3w		w9
+
+#define ENTRY(f) \
+  .text; \
+  .globl f; \
+  .align 0; \
+  .type f, %function; \
+  f: \
+  .cfi_startproc \
+
+#define END(f) \
+  .cfi_endproc; \
+  .size f, .-f; \
+
+ENTRY(android_memset16)
+	ands   A_lw, A_lw, #0xffff
+	b.eq	.Lzero_mem
+	orr	A_lw, A_lw, A_lw, lsl #16
+	b .Lexpand_to_64
+END(android_memset16)
+
+ENTRY(android_memset32)
+	cmp	    A_lw, #0
+	b.eq	.Lzero_mem
+.Lexpand_to_64:
+	orr	A_l, A_l, A_l, lsl #32
+.Ltail_maybe_long:
+	cmp	count, #64
+	b.ge	.Lnot_short
+.Ltail_maybe_tiny:
+	cmp	count, #15
+	b.le	.Ltail15tiny
+.Ltail63:
+	ands	tmp1, count, #0x30
+	b.eq	.Ltail15
+	add	dst, dst, tmp1
+	cmp	tmp1w, #0x20
+	b.eq	1f
+	b.lt	2f
+	stp	A_l, A_l, [dst, #-48]
+1:
+	stp	A_l, A_l, [dst, #-32]
+2:
+	stp	A_l, A_l, [dst, #-16]
+
+.Ltail15:
+	and	count, count, #15
+	add	dst, dst, count
+	stp	A_l, A_l, [dst, #-16]	/* Repeat some/all of last store. */
+	ret
+
+.Ltail15tiny:
+	/* Set up to 15 bytes.  Does not assume earlier memory
+	   being set.  */
+	tbz	count, #3, 1f
+	str	A_l, [dst], #8
+1:
+	tbz	count, #2, 1f
+	str	A_lw, [dst], #4
+1:
+	tbz	count, #1, 1f
+	strh	A_lw, [dst], #2
+1:
+	ret
+
+	/* Critical loop.  Start at a new cache line boundary.  Assuming
+	 * 64 bytes per line, this ensures the entire loop is in one line.  */
+	.p2align 6
+.Lnot_short:
+	neg	tmp2, dst
+	ands	tmp2, tmp2, #15
+	b.eq	2f
+	/* Bring DST to 128-bit (16-byte) alignment.  We know that there's
+	 * more than that to set, so we simply store 16 bytes and advance by
+	 * the amount required to reach alignment.  */
+	sub	count, count, tmp2
+	stp	A_l, A_l, [dst]
+	add	dst, dst, tmp2
+	/* There may be less than 63 bytes to go now.  */
+	cmp	count, #63
+	b.le	.Ltail63
+2:
+	sub	dst, dst, #16		/* Pre-bias.  */
+	sub	count, count, #64
+1:
+	stp	A_l, A_l, [dst, #16]
+	stp	A_l, A_l, [dst, #32]
+	stp	A_l, A_l, [dst, #48]
+	stp	A_l, A_l, [dst, #64]!
+	subs	count, count, #64
+	b.ge	1b
+	tst	count, #0x3f
+	add	dst, dst, #16
+	b.ne	.Ltail63
+	ret
+
+	/* For zeroing memory, check to see if we can use the ZVA feature to
+	 * zero entire 'cache' lines.  */
+.Lzero_mem:
+	mov	A_l, #0
+	cmp	count, #63
+	b.le	.Ltail_maybe_tiny
+	neg	tmp2, dst
+	ands	tmp2, tmp2, #15
+	b.eq	1f
+	sub	count, count, tmp2
+	stp	A_l, A_l, [dst]
+	add	dst, dst, tmp2
+	cmp	count, #63
+	b.le	.Ltail63
+1:
+	/* For zeroing small amounts of memory, it's not worth setting up
+	 * the line-clear code.  */
+	cmp	count, #128
+	b.lt	.Lnot_short
+	mrs	tmp1, dczid_el0
+	tbnz	tmp1, #4, .Lnot_short
+	mov	tmp3w, #4
+	and	zva_len, tmp1w, #15	/* Safety: other bits reserved.  */
+	lsl	zva_len, tmp3w, zva_len
+
+.Lzero_by_line:
+	/* Compute how far we need to go to become suitably aligned.  We're
+	 * already at quad-word alignment.  */
+	cmp	count, zva_len_x
+	b.lt	.Lnot_short		/* Not enough to reach alignment.  */
+	sub	zva_bits_x, zva_len_x, #1
+	neg	tmp2, dst
+	ands	tmp2, tmp2, zva_bits_x
+	b.eq	1f			/* Already aligned.  */
+	/* Not aligned, check that there's enough to copy after alignment.  */
+	sub	tmp1, count, tmp2
+	cmp	tmp1, #64
+	ccmp	tmp1, zva_len_x, #8, ge	/* NZCV=0b1000 */
+	b.lt	.Lnot_short
+	/* We know that there's at least 64 bytes to zero and that it's safe
+	 * to overrun by 64 bytes.  */
+	mov	count, tmp1
+2:
+	stp	A_l, A_l, [dst]
+	stp	A_l, A_l, [dst, #16]
+	stp	A_l, A_l, [dst, #32]
+	subs	tmp2, tmp2, #64
+	stp	A_l, A_l, [dst, #48]
+	add	dst, dst, #64
+	b.ge	2b
+	/* We've overrun a bit, so adjust dst downwards.  */
+	add	dst, dst, tmp2
+1:
+	sub	count, count, zva_len_x
+3:
+	dc	zva, dst
+	add	dst, dst, zva_len_x
+	subs	count, count, zva_len_x
+	b.ge	3b
+	ands	count, count, zva_bits_x
+	b.ne	.Ltail_maybe_long
+	ret
+END(android_memset32)
diff --git a/package/utils/adbd/src/libcutils/arch-mips/android_memset.c b/package/utils/adbd/src/libcutils/arch-mips/android_memset.c
new file mode 100644
index 0000000..bbc99fe
--- /dev/null
+++ b/package/utils/adbd/src/libcutils/arch-mips/android_memset.c
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2012 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 <cutils/memory.h>
+
+/* Use mips-assembler versions supplied by bionic/libc/arch-mips/string/memset.S: */
+void _memset16(uint16_t* dst, uint16_t value, size_t size);
+void _memset32(uint32_t* dst, uint32_t value, size_t size);
+
+void android_memset16(uint16_t* dst, uint16_t value, size_t size)
+{
+    _memset16(dst, value, size);
+}
+
+void android_memset32(uint32_t* dst, uint32_t value, size_t size)
+{
+    _memset32(dst, value, size);
+}
diff --git a/package/utils/adbd/src/libcutils/arch-x86/android_memset16.S b/package/utils/adbd/src/libcutils/arch-x86/android_memset16.S
new file mode 100755
index 0000000..f8b79bd
--- /dev/null
+++ b/package/utils/adbd/src/libcutils/arch-x86/android_memset16.S
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+/*
+ * Contributed by: Intel Corporation
+ */
+
+# include "cache_wrapper.S"
+# undef __i686
+# define USE_AS_ANDROID
+# define sse2_memset16_atom android_memset16
+# include "sse2-memset16-atom.S"
+
diff --git a/package/utils/adbd/src/libcutils/arch-x86/android_memset32.S b/package/utils/adbd/src/libcutils/arch-x86/android_memset32.S
new file mode 100755
index 0000000..6249fce
--- /dev/null
+++ b/package/utils/adbd/src/libcutils/arch-x86/android_memset32.S
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+/*
+ * Contributed by: Intel Corporation
+ */
+
+# include "cache_wrapper.S"
+# undef __i686
+# define USE_AS_ANDROID
+# define sse2_memset32_atom android_memset32
+# include "sse2-memset32-atom.S"
+
diff --git a/package/utils/adbd/src/libcutils/arch-x86/cache.h b/package/utils/adbd/src/libcutils/arch-x86/cache.h
new file mode 100644
index 0000000..1c22fea
--- /dev/null
+++ b/package/utils/adbd/src/libcutils/arch-x86/cache.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#if defined(__slm__)
+/* Values are optimized for Silvermont */
+#define SHARED_CACHE_SIZE   (1024*1024)         /* Silvermont L2 Cache */
+#define DATA_CACHE_SIZE     (24*1024)           /* Silvermont L1 Data Cache */
+#else
+/* Values are optimized for Atom */
+#define SHARED_CACHE_SIZE   (512*1024)          /* Atom L2 Cache */
+#define DATA_CACHE_SIZE     (24*1024)           /* Atom L1 Data Cache */
+#endif
+
+#define SHARED_CACHE_SIZE_HALF  (SHARED_CACHE_SIZE / 2)
+#define DATA_CACHE_SIZE_HALF    (DATA_CACHE_SIZE / 2)
diff --git a/package/utils/adbd/src/libcutils/arch-x86/cache_wrapper.S b/package/utils/adbd/src/libcutils/arch-x86/cache_wrapper.S
new file mode 100644
index 0000000..9eee25c
--- /dev/null
+++ b/package/utils/adbd/src/libcutils/arch-x86/cache_wrapper.S
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+/*
+ * Contributed by: Intel Corporation
+ */
+
+#if defined(__slm__)
+/* Values are optimized for Silvermont */
+#define SHARED_CACHE_SIZE   (1024*1024)         /* Silvermont L2 Cache */
+#define DATA_CACHE_SIZE     (24*1024)           /* Silvermont L1 Data Cache */
+#else
+/* Values are optimized for Atom */
+#define SHARED_CACHE_SIZE   (512*1024)          /* Atom L2 Cache */
+#define DATA_CACHE_SIZE     (24*1024)           /* Atom L1 Data Cache */
+#endif
+
+#define SHARED_CACHE_SIZE_HALF  (SHARED_CACHE_SIZE / 2)
+#define DATA_CACHE_SIZE_HALF    (DATA_CACHE_SIZE / 2)
diff --git a/package/utils/adbd/src/libcutils/arch-x86/sse2-memset16-atom.S b/package/utils/adbd/src/libcutils/arch-x86/sse2-memset16-atom.S
new file mode 100755
index 0000000..c2a762b
--- /dev/null
+++ b/package/utils/adbd/src/libcutils/arch-x86/sse2-memset16-atom.S
@@ -0,0 +1,722 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+/*
+ * Contributed by: Intel Corporation
+ */
+
+#ifndef L
+# define L(label)	.L##label
+#endif
+
+#ifndef ALIGN
+# define ALIGN(n)	.p2align n
+#endif
+
+#ifndef cfi_startproc
+# define cfi_startproc			.cfi_startproc
+#endif
+
+#ifndef cfi_endproc
+# define cfi_endproc			.cfi_endproc
+#endif
+
+#ifndef cfi_rel_offset
+# define cfi_rel_offset(reg, off)	.cfi_rel_offset reg, off
+#endif
+
+#ifndef cfi_restore
+# define cfi_restore(reg)		.cfi_restore reg
+#endif
+
+#ifndef cfi_adjust_cfa_offset
+# define cfi_adjust_cfa_offset(off)	.cfi_adjust_cfa_offset off
+#endif
+
+#ifndef ENTRY
+# define ENTRY(name)			\
+	.type name,  @function; 	\
+	.globl name;			\
+	.p2align 4;			\
+name:					\
+	cfi_startproc
+#endif
+
+#ifndef END
+# define END(name)			\
+	cfi_endproc;			\
+	.size name, .-name
+#endif
+
+#define CFI_PUSH(REG)						\
+  cfi_adjust_cfa_offset (4);					\
+  cfi_rel_offset (REG, 0)
+
+#define CFI_POP(REG)						\
+  cfi_adjust_cfa_offset (-4);					\
+  cfi_restore (REG)
+
+#define PUSH(REG)	pushl REG; CFI_PUSH (REG)
+#define POP(REG)	popl REG; CFI_POP (REG)
+
+#ifdef USE_AS_BZERO16
+# define DEST		PARMS
+# define LEN		DEST+4
+#else
+# define DEST		PARMS
+# define CHR		DEST+4
+# define LEN		CHR+4
+#endif
+
+#if 1
+# define SETRTNVAL
+#else
+# define SETRTNVAL	movl DEST(%esp), %eax
+#endif
+
+#if (defined SHARED || defined __PIC__)
+# define ENTRANCE	PUSH (%ebx);
+# define RETURN_END	POP (%ebx); ret
+# define RETURN		RETURN_END; CFI_PUSH (%ebx)
+# define PARMS		8		/* Preserve EBX.  */
+# define JMPTBL(I, B)	I - B
+
+/* Load an entry in a jump table into EBX and branch to it.  TABLE is a
+   jump table with relative offsets.   */
+# define BRANCH_TO_JMPTBL_ENTRY(TABLE)				\
+    /* We first load PC into EBX.  */				\
+    call	__i686.get_pc_thunk.bx;				\
+    /* Get the address of the jump table.  */			\
+    add		$(TABLE - .), %ebx;				\
+    /* Get the entry and convert the relative offset to the	\
+       absolute address.  */					\
+    add		(%ebx,%ecx,4), %ebx;				\
+    /* We loaded the jump table and adjuested EDX. Go.  */	\
+    jmp		*%ebx
+
+	.section	.gnu.linkonce.t.__i686.get_pc_thunk.bx,"ax",@progbits
+	.globl	__i686.get_pc_thunk.bx
+	.hidden	__i686.get_pc_thunk.bx
+	ALIGN (4)
+	.type	__i686.get_pc_thunk.bx,@function
+__i686.get_pc_thunk.bx:
+	movl	(%esp), %ebx
+	ret
+#else
+# define ENTRANCE
+# define RETURN_END	ret
+# define RETURN		RETURN_END
+# define PARMS		4
+# define JMPTBL(I, B)	I
+
+/* Branch to an entry in a jump table.  TABLE is a jump table with
+   absolute offsets.  */
+# define BRANCH_TO_JMPTBL_ENTRY(TABLE)				\
+    jmp		*TABLE(,%ecx,4)
+#endif
+
+	.section .text.sse2,"ax",@progbits
+	ALIGN (4)
+ENTRY (sse2_memset16_atom)
+	ENTRANCE
+
+	movl	LEN(%esp), %ecx
+#ifdef USE_AS_ANDROID
+	shr	$1, %ecx
+#endif
+#ifdef USE_AS_BZERO16
+	xor	%eax, %eax
+#else
+	movzwl	CHR(%esp), %eax
+	mov	%eax, %edx
+	shl	$16, %eax
+	or	%edx, %eax
+#endif
+	movl	DEST(%esp), %edx
+	cmp	$32, %ecx
+	jae	L(32wordsormore)
+
+L(write_less32words):
+	lea	(%edx, %ecx, 2), %edx
+	BRANCH_TO_JMPTBL_ENTRY (L(table_less32words))
+
+
+	.pushsection .rodata.sse2,"a",@progbits
+	ALIGN (2)
+L(table_less32words):
+	.int	JMPTBL (L(write_0words), L(table_less32words))
+	.int	JMPTBL (L(write_1words), L(table_less32words))
+	.int	JMPTBL (L(write_2words), L(table_less32words))
+	.int	JMPTBL (L(write_3words), L(table_less32words))
+	.int	JMPTBL (L(write_4words), L(table_less32words))
+	.int	JMPTBL (L(write_5words), L(table_less32words))
+	.int	JMPTBL (L(write_6words), L(table_less32words))
+	.int	JMPTBL (L(write_7words), L(table_less32words))
+	.int	JMPTBL (L(write_8words), L(table_less32words))
+	.int	JMPTBL (L(write_9words), L(table_less32words))
+	.int	JMPTBL (L(write_10words), L(table_less32words))
+	.int	JMPTBL (L(write_11words), L(table_less32words))
+	.int	JMPTBL (L(write_12words), L(table_less32words))
+	.int	JMPTBL (L(write_13words), L(table_less32words))
+	.int	JMPTBL (L(write_14words), L(table_less32words))
+	.int	JMPTBL (L(write_15words), L(table_less32words))
+	.int	JMPTBL (L(write_16words), L(table_less32words))
+	.int	JMPTBL (L(write_17words), L(table_less32words))
+	.int	JMPTBL (L(write_18words), L(table_less32words))
+	.int	JMPTBL (L(write_19words), L(table_less32words))
+	.int	JMPTBL (L(write_20words), L(table_less32words))
+	.int	JMPTBL (L(write_21words), L(table_less32words))
+	.int	JMPTBL (L(write_22words), L(table_less32words))
+	.int	JMPTBL (L(write_23words), L(table_less32words))
+	.int	JMPTBL (L(write_24words), L(table_less32words))
+	.int	JMPTBL (L(write_25words), L(table_less32words))
+	.int	JMPTBL (L(write_26words), L(table_less32words))
+	.int	JMPTBL (L(write_27words), L(table_less32words))
+	.int	JMPTBL (L(write_28words), L(table_less32words))
+	.int	JMPTBL (L(write_29words), L(table_less32words))
+	.int	JMPTBL (L(write_30words), L(table_less32words))
+	.int	JMPTBL (L(write_31words), L(table_less32words))
+	.popsection
+
+	ALIGN (4)
+L(write_28words):
+	movl	%eax, -56(%edx)
+	movl	%eax, -52(%edx)
+L(write_24words):
+	movl	%eax, -48(%edx)
+	movl	%eax, -44(%edx)
+L(write_20words):
+	movl	%eax, -40(%edx)
+	movl	%eax, -36(%edx)
+L(write_16words):
+	movl	%eax, -32(%edx)
+	movl	%eax, -28(%edx)
+L(write_12words):
+	movl	%eax, -24(%edx)
+	movl	%eax, -20(%edx)
+L(write_8words):
+	movl	%eax, -16(%edx)
+	movl	%eax, -12(%edx)
+L(write_4words):
+	movl	%eax, -8(%edx)
+	movl	%eax, -4(%edx)
+L(write_0words):
+	SETRTNVAL
+	RETURN
+
+	ALIGN (4)
+L(write_29words):
+	movl	%eax, -58(%edx)
+	movl	%eax, -54(%edx)
+L(write_25words):
+	movl	%eax, -50(%edx)
+	movl	%eax, -46(%edx)
+L(write_21words):
+	movl	%eax, -42(%edx)
+	movl	%eax, -38(%edx)
+L(write_17words):
+	movl	%eax, -34(%edx)
+	movl	%eax, -30(%edx)
+L(write_13words):
+	movl	%eax, -26(%edx)
+	movl	%eax, -22(%edx)
+L(write_9words):
+	movl	%eax, -18(%edx)
+	movl	%eax, -14(%edx)
+L(write_5words):
+	movl	%eax, -10(%edx)
+	movl	%eax, -6(%edx)
+L(write_1words):
+	mov	%ax, -2(%edx)
+	SETRTNVAL
+	RETURN
+
+	ALIGN (4)
+L(write_30words):
+	movl	%eax, -60(%edx)
+	movl	%eax, -56(%edx)
+L(write_26words):
+	movl	%eax, -52(%edx)
+	movl	%eax, -48(%edx)
+L(write_22words):
+	movl	%eax, -44(%edx)
+	movl	%eax, -40(%edx)
+L(write_18words):
+	movl	%eax, -36(%edx)
+	movl	%eax, -32(%edx)
+L(write_14words):
+	movl	%eax, -28(%edx)
+	movl	%eax, -24(%edx)
+L(write_10words):
+	movl	%eax, -20(%edx)
+	movl	%eax, -16(%edx)
+L(write_6words):
+	movl	%eax, -12(%edx)
+	movl	%eax, -8(%edx)
+L(write_2words):
+	movl	%eax, -4(%edx)
+	SETRTNVAL
+	RETURN
+
+	ALIGN (4)
+L(write_31words):
+	movl	%eax, -62(%edx)
+	movl	%eax, -58(%edx)
+L(write_27words):
+	movl	%eax, -54(%edx)
+	movl	%eax, -50(%edx)
+L(write_23words):
+	movl	%eax, -46(%edx)
+	movl	%eax, -42(%edx)
+L(write_19words):
+	movl	%eax, -38(%edx)
+	movl	%eax, -34(%edx)
+L(write_15words):
+	movl	%eax, -30(%edx)
+	movl	%eax, -26(%edx)
+L(write_11words):
+	movl	%eax, -22(%edx)
+	movl	%eax, -18(%edx)
+L(write_7words):
+	movl	%eax, -14(%edx)
+	movl	%eax, -10(%edx)
+L(write_3words):
+	movl	%eax, -6(%edx)
+	movw	%ax, -2(%edx)
+	SETRTNVAL
+	RETURN
+
+	ALIGN (4)
+
+L(32wordsormore):
+	shl	$1, %ecx
+	test	$0x01, %edx
+	jz	L(aligned2bytes)
+	mov	%eax, (%edx)
+	mov	%eax, -4(%edx, %ecx)
+	sub	$2, %ecx
+	add	$1, %edx
+	rol	$8, %eax
+L(aligned2bytes):
+#ifdef USE_AS_BZERO16
+	pxor	%xmm0, %xmm0
+#else
+	movd	%eax, %xmm0
+	pshufd	$0, %xmm0, %xmm0
+#endif
+	testl	$0xf, %edx
+	jz	L(aligned_16)
+/* ECX > 32 and EDX is not 16 byte aligned.  */
+L(not_aligned_16):
+	movdqu	%xmm0, (%edx)
+	movl	%edx, %eax
+	and	$-16, %edx
+	add	$16, %edx
+	sub	%edx, %eax
+	add	%eax, %ecx
+	movd	%xmm0, %eax
+
+	ALIGN (4)
+L(aligned_16):
+	cmp	$128, %ecx
+	jae	L(128bytesormore)
+
+L(aligned_16_less128bytes):
+	add	%ecx, %edx
+	shr	$1, %ecx
+	BRANCH_TO_JMPTBL_ENTRY (L(table_16_128bytes))
+
+	ALIGN (4)
+L(128bytesormore):
+#ifdef SHARED_CACHE_SIZE
+	PUSH (%ebx)
+	mov	$SHARED_CACHE_SIZE, %ebx
+#else
+# if (defined SHARED || defined __PIC__)
+	call	__i686.get_pc_thunk.bx
+	add	$_GLOBAL_OFFSET_TABLE_, %ebx
+	mov	__x86_shared_cache_size@GOTOFF(%ebx), %ebx
+# else
+	PUSH (%ebx)
+	mov	__x86_shared_cache_size, %ebx
+# endif
+#endif
+	cmp	%ebx, %ecx
+	jae	L(128bytesormore_nt_start)
+
+	
+#ifdef DATA_CACHE_SIZE
+	POP (%ebx)
+# define RESTORE_EBX_STATE CFI_PUSH (%ebx)
+	cmp	$DATA_CACHE_SIZE, %ecx
+#else
+# if (defined SHARED || defined __PIC__)
+#  define RESTORE_EBX_STATE
+	call	__i686.get_pc_thunk.bx
+	add	$_GLOBAL_OFFSET_TABLE_, %ebx
+	cmp	__x86_data_cache_size@GOTOFF(%ebx), %ecx
+# else
+	POP (%ebx)
+#  define RESTORE_EBX_STATE CFI_PUSH (%ebx)
+	cmp	__x86_data_cache_size, %ecx
+# endif
+#endif
+
+	jae	L(128bytes_L2_normal)
+	subl	$128, %ecx
+L(128bytesormore_normal):
+	sub	$128, %ecx
+	movdqa	%xmm0, (%edx)
+	movdqa	%xmm0, 0x10(%edx)
+	movdqa	%xmm0, 0x20(%edx)
+	movdqa	%xmm0, 0x30(%edx)
+	movdqa	%xmm0, 0x40(%edx)
+	movdqa	%xmm0, 0x50(%edx)
+	movdqa	%xmm0, 0x60(%edx)
+	movdqa	%xmm0, 0x70(%edx)
+	lea	128(%edx), %edx
+	jb	L(128bytesless_normal)
+
+
+	sub	$128, %ecx
+	movdqa	%xmm0, (%edx)
+	movdqa	%xmm0, 0x10(%edx)
+	movdqa	%xmm0, 0x20(%edx)
+	movdqa	%xmm0, 0x30(%edx)
+	movdqa	%xmm0, 0x40(%edx)
+	movdqa	%xmm0, 0x50(%edx)
+	movdqa	%xmm0, 0x60(%edx)
+	movdqa	%xmm0, 0x70(%edx)
+	lea	128(%edx), %edx
+	jae	L(128bytesormore_normal)
+
+L(128bytesless_normal):
+	lea	128(%ecx), %ecx
+	add	%ecx, %edx
+	shr	$1, %ecx
+	BRANCH_TO_JMPTBL_ENTRY (L(table_16_128bytes))
+
+	ALIGN (4)
+L(128bytes_L2_normal):
+	prefetcht0	0x380(%edx)
+	prefetcht0	0x3c0(%edx)
+	sub	$128, %ecx
+	movdqa	%xmm0, (%edx)
+	movaps	%xmm0, 0x10(%edx)
+	movaps	%xmm0, 0x20(%edx)
+	movaps	%xmm0, 0x30(%edx)
+	movaps	%xmm0, 0x40(%edx)
+	movaps	%xmm0, 0x50(%edx)
+	movaps	%xmm0, 0x60(%edx)
+	movaps	%xmm0, 0x70(%edx)
+	add	$128, %edx
+	cmp	$128, %ecx 	
+	jae	L(128bytes_L2_normal)
+
+L(128bytesless_L2_normal):
+	add	%ecx, %edx
+	shr	$1, %ecx
+	BRANCH_TO_JMPTBL_ENTRY (L(table_16_128bytes))
+
+	RESTORE_EBX_STATE
+L(128bytesormore_nt_start):
+	sub	%ebx, %ecx
+	mov	%ebx, %eax
+	and	$0x7f, %eax
+	add	%eax, %ecx
+	movd	%xmm0, %eax
+	ALIGN (4)
+L(128bytesormore_shared_cache_loop):
+	prefetcht0	0x3c0(%edx)
+	prefetcht0	0x380(%edx)
+	sub	$0x80, %ebx
+	movdqa	%xmm0, (%edx)
+	movdqa	%xmm0, 0x10(%edx)
+	movdqa	%xmm0, 0x20(%edx)
+	movdqa	%xmm0, 0x30(%edx)
+	movdqa	%xmm0, 0x40(%edx)
+	movdqa	%xmm0, 0x50(%edx)
+	movdqa	%xmm0, 0x60(%edx)
+	movdqa	%xmm0, 0x70(%edx)
+	add	$0x80, %edx
+	cmp	$0x80, %ebx
+	jae	L(128bytesormore_shared_cache_loop)
+	cmp	$0x80, %ecx
+	jb	L(shared_cache_loop_end)
+	ALIGN (4)
+L(128bytesormore_nt):
+	sub	$0x80, %ecx
+	movntdq	%xmm0, (%edx)
+	movntdq	%xmm0, 0x10(%edx)
+	movntdq	%xmm0, 0x20(%edx)
+	movntdq	%xmm0, 0x30(%edx)
+	movntdq	%xmm0, 0x40(%edx)
+	movntdq	%xmm0, 0x50(%edx)
+	movntdq	%xmm0, 0x60(%edx)
+	movntdq	%xmm0, 0x70(%edx)
+	add	$0x80, %edx
+	cmp	$0x80, %ecx
+	jae	L(128bytesormore_nt)
+	sfence
+L(shared_cache_loop_end):
+#if defined DATA_CACHE_SIZE || !(defined SHARED || defined __PIC__)
+	POP (%ebx)
+#endif
+	add	%ecx, %edx
+	shr	$1, %ecx
+	BRANCH_TO_JMPTBL_ENTRY (L(table_16_128bytes))
+
+
+	.pushsection .rodata.sse2,"a",@progbits
+	ALIGN (2)
+L(table_16_128bytes):
+	.int	JMPTBL (L(aligned_16_0bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_2bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_4bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_6bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_8bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_10bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_12bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_14bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_16bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_18bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_20bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_22bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_24bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_26bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_28bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_30bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_32bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_34bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_36bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_38bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_40bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_42bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_44bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_46bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_48bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_50bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_52bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_54bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_56bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_58bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_60bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_62bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_64bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_66bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_68bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_70bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_72bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_74bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_76bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_78bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_80bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_82bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_84bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_86bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_88bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_90bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_92bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_94bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_96bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_98bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_100bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_102bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_104bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_106bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_108bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_110bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_112bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_114bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_116bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_118bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_120bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_122bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_124bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_126bytes), L(table_16_128bytes))
+	.popsection
+
+
+	ALIGN (4)
+L(aligned_16_112bytes):
+	movdqa	%xmm0, -112(%edx)
+L(aligned_16_96bytes):
+	movdqa	%xmm0, -96(%edx)
+L(aligned_16_80bytes):
+	movdqa	%xmm0, -80(%edx)
+L(aligned_16_64bytes):
+	movdqa	%xmm0, -64(%edx)
+L(aligned_16_48bytes):
+	movdqa	%xmm0, -48(%edx)
+L(aligned_16_32bytes):
+	movdqa	%xmm0, -32(%edx)
+L(aligned_16_16bytes):
+	movdqa	%xmm0, -16(%edx)
+L(aligned_16_0bytes):
+	SETRTNVAL
+	RETURN
+
+
+	ALIGN (4)
+L(aligned_16_114bytes):
+	movdqa	%xmm0, -114(%edx)
+L(aligned_16_98bytes):
+	movdqa	%xmm0, -98(%edx)
+L(aligned_16_82bytes):
+	movdqa	%xmm0, -82(%edx)
+L(aligned_16_66bytes):
+	movdqa	%xmm0, -66(%edx)
+L(aligned_16_50bytes):
+	movdqa	%xmm0, -50(%edx)
+L(aligned_16_34bytes):
+	movdqa	%xmm0, -34(%edx)
+L(aligned_16_18bytes):
+	movdqa	%xmm0, -18(%edx)
+L(aligned_16_2bytes):
+	movw	%ax, -2(%edx)
+	SETRTNVAL
+	RETURN
+
+	ALIGN (4)
+L(aligned_16_116bytes):
+	movdqa	%xmm0, -116(%edx)
+L(aligned_16_100bytes):
+	movdqa	%xmm0, -100(%edx)
+L(aligned_16_84bytes):
+	movdqa	%xmm0, -84(%edx)
+L(aligned_16_68bytes):
+	movdqa	%xmm0, -68(%edx)
+L(aligned_16_52bytes):
+	movdqa	%xmm0, -52(%edx)
+L(aligned_16_36bytes):
+	movdqa	%xmm0, -36(%edx)
+L(aligned_16_20bytes):
+	movdqa	%xmm0, -20(%edx)
+L(aligned_16_4bytes):
+	movl	%eax, -4(%edx)
+	SETRTNVAL
+	RETURN
+
+
+	ALIGN (4)
+L(aligned_16_118bytes):
+	movdqa	%xmm0, -118(%edx)
+L(aligned_16_102bytes):
+	movdqa	%xmm0, -102(%edx)
+L(aligned_16_86bytes):
+	movdqa	%xmm0, -86(%edx)
+L(aligned_16_70bytes):
+	movdqa	%xmm0, -70(%edx)
+L(aligned_16_54bytes):
+	movdqa	%xmm0, -54(%edx)
+L(aligned_16_38bytes):
+	movdqa	%xmm0, -38(%edx)
+L(aligned_16_22bytes):
+	movdqa	%xmm0, -22(%edx)
+L(aligned_16_6bytes):
+	movl	%eax, -6(%edx)
+	movw	%ax, -2(%edx)
+	SETRTNVAL
+	RETURN
+
+
+	ALIGN (4)
+L(aligned_16_120bytes):
+	movdqa	%xmm0, -120(%edx)
+L(aligned_16_104bytes):
+	movdqa	%xmm0, -104(%edx)
+L(aligned_16_88bytes):
+	movdqa	%xmm0, -88(%edx)
+L(aligned_16_72bytes):
+	movdqa	%xmm0, -72(%edx)
+L(aligned_16_56bytes):
+	movdqa	%xmm0, -56(%edx)
+L(aligned_16_40bytes):
+	movdqa	%xmm0, -40(%edx)
+L(aligned_16_24bytes):
+	movdqa	%xmm0, -24(%edx)
+L(aligned_16_8bytes):
+	movq	%xmm0, -8(%edx)
+	SETRTNVAL
+	RETURN
+
+
+	ALIGN (4)
+L(aligned_16_122bytes):
+	movdqa	%xmm0, -122(%edx)
+L(aligned_16_106bytes):
+	movdqa	%xmm0, -106(%edx)
+L(aligned_16_90bytes):
+	movdqa	%xmm0, -90(%edx)
+L(aligned_16_74bytes):
+	movdqa	%xmm0, -74(%edx)
+L(aligned_16_58bytes):
+	movdqa	%xmm0, -58(%edx)
+L(aligned_16_42bytes):
+	movdqa	%xmm0, -42(%edx)
+L(aligned_16_26bytes):
+	movdqa	%xmm0, -26(%edx)
+L(aligned_16_10bytes):
+	movq	%xmm0, -10(%edx)
+	movw	%ax, -2(%edx)
+	SETRTNVAL
+	RETURN
+
+
+	ALIGN (4)
+L(aligned_16_124bytes):
+	movdqa	%xmm0, -124(%edx)
+L(aligned_16_108bytes):
+	movdqa	%xmm0, -108(%edx)
+L(aligned_16_92bytes):
+	movdqa	%xmm0, -92(%edx)
+L(aligned_16_76bytes):
+	movdqa	%xmm0, -76(%edx)
+L(aligned_16_60bytes):
+	movdqa	%xmm0, -60(%edx)
+L(aligned_16_44bytes):
+	movdqa	%xmm0, -44(%edx)
+L(aligned_16_28bytes):
+	movdqa	%xmm0, -28(%edx)
+L(aligned_16_12bytes):
+	movq	%xmm0, -12(%edx)
+	movl	%eax, -4(%edx)
+	SETRTNVAL
+	RETURN
+
+
+	ALIGN (4)
+L(aligned_16_126bytes):
+	movdqa	%xmm0, -126(%edx)
+L(aligned_16_110bytes):
+	movdqa	%xmm0, -110(%edx)
+L(aligned_16_94bytes):
+	movdqa	%xmm0, -94(%edx)
+L(aligned_16_78bytes):
+	movdqa	%xmm0, -78(%edx)
+L(aligned_16_62bytes):
+	movdqa	%xmm0, -62(%edx)
+L(aligned_16_46bytes):
+	movdqa	%xmm0, -46(%edx)
+L(aligned_16_30bytes):
+	movdqa	%xmm0, -30(%edx)
+L(aligned_16_14bytes):
+	movq	%xmm0, -14(%edx)
+	movl	%eax, -6(%edx)
+	movw	%ax, -2(%edx)
+	SETRTNVAL
+	RETURN
+
+END (sse2_memset16_atom)
diff --git a/package/utils/adbd/src/libcutils/arch-x86/sse2-memset32-atom.S b/package/utils/adbd/src/libcutils/arch-x86/sse2-memset32-atom.S
new file mode 100755
index 0000000..05eb64f
--- /dev/null
+++ b/package/utils/adbd/src/libcutils/arch-x86/sse2-memset32-atom.S
@@ -0,0 +1,513 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+/*
+ * Contributed by: Intel Corporation
+ */
+
+#ifndef L
+# define L(label)	.L##label
+#endif
+
+#ifndef ALIGN
+# define ALIGN(n)	.p2align n
+#endif
+
+#ifndef cfi_startproc
+# define cfi_startproc			.cfi_startproc
+#endif
+
+#ifndef cfi_endproc
+# define cfi_endproc			.cfi_endproc
+#endif
+
+#ifndef cfi_rel_offset
+# define cfi_rel_offset(reg, off)	.cfi_rel_offset reg, off
+#endif
+
+#ifndef cfi_restore
+# define cfi_restore(reg)		.cfi_restore reg
+#endif
+
+#ifndef cfi_adjust_cfa_offset
+# define cfi_adjust_cfa_offset(off)	.cfi_adjust_cfa_offset off
+#endif
+
+#ifndef ENTRY
+# define ENTRY(name)			\
+	.type name,  @function; 	\
+	.globl name;			\
+	.p2align 4;			\
+name:					\
+	cfi_startproc
+#endif
+
+#ifndef END
+# define END(name)			\
+	cfi_endproc;			\
+	.size name, .-name
+#endif
+
+#define CFI_PUSH(REG)						\
+  cfi_adjust_cfa_offset (4);					\
+  cfi_rel_offset (REG, 0)
+
+#define CFI_POP(REG)						\
+  cfi_adjust_cfa_offset (-4);					\
+  cfi_restore (REG)
+
+#define PUSH(REG)	pushl REG; CFI_PUSH (REG)
+#define POP(REG)	popl REG; CFI_POP (REG)
+
+#ifdef USE_AS_BZERO32
+# define DEST		PARMS
+# define LEN		DEST+4
+#else
+# define DEST		PARMS
+# define DWDS		DEST+4
+# define LEN		DWDS+4
+#endif
+
+#ifdef USE_AS_WMEMSET32
+# define SETRTNVAL	movl DEST(%esp), %eax
+#else
+# define SETRTNVAL
+#endif
+
+#if (defined SHARED || defined __PIC__)
+# define ENTRANCE	PUSH (%ebx);
+# define RETURN_END	POP (%ebx); ret
+# define RETURN		RETURN_END; CFI_PUSH (%ebx)
+# define PARMS		8		/* Preserve EBX.  */
+# define JMPTBL(I, B)	I - B
+
+/* Load an entry in a jump table into EBX and branch to it.  TABLE is a
+   jump table with relative offsets.   */
+# define BRANCH_TO_JMPTBL_ENTRY(TABLE)				\
+    /* We first load PC into EBX.  */				\
+    call	__i686.get_pc_thunk.bx;				\
+    /* Get the address of the jump table.  */			\
+    add		$(TABLE - .), %ebx;				\
+    /* Get the entry and convert the relative offset to the	\
+       absolute address.  */					\
+    add		(%ebx,%ecx,4), %ebx;				\
+    /* We loaded the jump table and adjuested EDX. Go.  */	\
+    jmp		*%ebx
+
+	.section	.gnu.linkonce.t.__i686.get_pc_thunk.bx,"ax",@progbits
+	.globl	__i686.get_pc_thunk.bx
+	.hidden	__i686.get_pc_thunk.bx
+	ALIGN (4)
+	.type	__i686.get_pc_thunk.bx,@function
+__i686.get_pc_thunk.bx:
+	movl	(%esp), %ebx
+	ret
+#else
+# define ENTRANCE
+# define RETURN_END	ret
+# define RETURN		RETURN_END
+# define PARMS		4
+# define JMPTBL(I, B)	I
+
+/* Branch to an entry in a jump table.  TABLE is a jump table with
+   absolute offsets.  */
+# define BRANCH_TO_JMPTBL_ENTRY(TABLE)				\
+    jmp		*TABLE(,%ecx,4)
+#endif
+
+	.section .text.sse2,"ax",@progbits
+	ALIGN (4)
+ENTRY (sse2_memset32_atom)
+	ENTRANCE
+
+	movl	LEN(%esp), %ecx
+#ifdef USE_AS_ANDROID
+	shr     $2, %ecx
+#endif
+#ifdef USE_AS_BZERO32
+	xor	%eax, %eax
+#else
+	mov	DWDS(%esp), %eax
+	mov	%eax, %edx
+#endif
+	movl	DEST(%esp), %edx
+	cmp	$16, %ecx
+	jae	L(16dbwordsormore)
+
+L(write_less16dbwords):
+	lea	(%edx, %ecx, 4), %edx
+	BRANCH_TO_JMPTBL_ENTRY (L(table_less16dbwords))
+
+	.pushsection .rodata.sse2,"a",@progbits
+	ALIGN (2)
+L(table_less16dbwords):
+	.int	JMPTBL (L(write_0dbwords), L(table_less16dbwords))
+	.int	JMPTBL (L(write_1dbwords), L(table_less16dbwords))
+	.int	JMPTBL (L(write_2dbwords), L(table_less16dbwords))
+	.int	JMPTBL (L(write_3dbwords), L(table_less16dbwords))
+	.int	JMPTBL (L(write_4dbwords), L(table_less16dbwords))
+	.int	JMPTBL (L(write_5dbwords), L(table_less16dbwords))
+	.int	JMPTBL (L(write_6dbwords), L(table_less16dbwords))
+	.int	JMPTBL (L(write_7dbwords), L(table_less16dbwords))
+	.int	JMPTBL (L(write_8dbwords), L(table_less16dbwords))
+	.int	JMPTBL (L(write_9dbwords), L(table_less16dbwords))
+	.int	JMPTBL (L(write_10dbwords), L(table_less16dbwords))
+	.int	JMPTBL (L(write_11dbwords), L(table_less16dbwords))
+	.int	JMPTBL (L(write_12dbwords), L(table_less16dbwords))
+	.int	JMPTBL (L(write_13dbwords), L(table_less16dbwords))
+	.int	JMPTBL (L(write_14dbwords), L(table_less16dbwords))
+	.int	JMPTBL (L(write_15dbwords), L(table_less16dbwords))
+	.popsection
+
+	ALIGN (4)
+L(write_15dbwords):
+	movl	%eax, -60(%edx)
+L(write_14dbwords):
+	movl	%eax, -56(%edx)
+L(write_13dbwords):
+	movl	%eax, -52(%edx)
+L(write_12dbwords):
+	movl	%eax, -48(%edx)
+L(write_11dbwords):
+	movl	%eax, -44(%edx)
+L(write_10dbwords):
+	movl	%eax, -40(%edx)
+L(write_9dbwords):
+	movl	%eax, -36(%edx)
+L(write_8dbwords):
+	movl	%eax, -32(%edx)
+L(write_7dbwords):
+	movl	%eax, -28(%edx)
+L(write_6dbwords):
+	movl	%eax, -24(%edx)
+L(write_5dbwords):
+	movl	%eax, -20(%edx)
+L(write_4dbwords):
+	movl	%eax, -16(%edx)
+L(write_3dbwords):
+	movl	%eax, -12(%edx)
+L(write_2dbwords):
+	movl	%eax, -8(%edx)
+L(write_1dbwords):
+	movl	%eax, -4(%edx)
+L(write_0dbwords):
+	SETRTNVAL
+	RETURN
+
+	ALIGN (4)
+L(16dbwordsormore):
+	test	$3, %edx
+	jz	L(aligned4bytes)
+	mov	%eax, (%edx)
+	mov	%eax, -4(%edx, %ecx, 4)
+	sub	$1, %ecx
+	rol	$24, %eax
+	add	$1, %edx
+	test	$3, %edx
+	jz	L(aligned4bytes)
+	ror	$8, %eax
+	add	$1, %edx
+	test	$3, %edx
+	jz	L(aligned4bytes)
+	ror	$8, %eax
+	add	$1, %edx
+L(aligned4bytes):
+	shl	$2, %ecx
+
+#ifdef USE_AS_BZERO32
+	pxor	%xmm0, %xmm0
+#else
+	movd	%eax, %xmm0
+	pshufd	$0, %xmm0, %xmm0
+#endif
+	testl	$0xf, %edx
+	jz	L(aligned_16)
+/* ECX > 32 and EDX is not 16 byte aligned.  */
+L(not_aligned_16):
+	movdqu	%xmm0, (%edx)
+	movl	%edx, %eax
+	and	$-16, %edx
+	add	$16, %edx
+	sub	%edx, %eax
+	add	%eax, %ecx
+	movd	%xmm0, %eax
+	ALIGN (4)
+L(aligned_16):
+	cmp	$128, %ecx
+	jae	L(128bytesormore)
+
+L(aligned_16_less128bytes):
+	add	%ecx, %edx
+	shr	$2, %ecx
+	BRANCH_TO_JMPTBL_ENTRY (L(table_16_128bytes))
+
+	ALIGN (4)
+L(128bytesormore):
+#ifdef SHARED_CACHE_SIZE
+	PUSH (%ebx)
+	mov	$SHARED_CACHE_SIZE, %ebx
+#else
+# if (defined SHARED || defined __PIC__)
+	call	__i686.get_pc_thunk.bx
+	add	$_GLOBAL_OFFSET_TABLE_, %ebx
+	mov	__x86_shared_cache_size@GOTOFF(%ebx), %ebx
+# else
+	PUSH (%ebx)
+	mov	__x86_shared_cache_size, %ebx
+# endif
+#endif
+	cmp	%ebx, %ecx
+	jae	L(128bytesormore_nt_start)
+	
+#ifdef DATA_CACHE_SIZE
+	POP (%ebx)
+# define RESTORE_EBX_STATE CFI_PUSH (%ebx)
+	cmp	$DATA_CACHE_SIZE, %ecx
+#else
+# if (defined SHARED || defined __PIC__)
+#  define RESTORE_EBX_STATE
+	call	__i686.get_pc_thunk.bx
+	add	$_GLOBAL_OFFSET_TABLE_, %ebx
+	cmp	__x86_data_cache_size@GOTOFF(%ebx), %ecx
+# else
+	POP (%ebx)
+#  define RESTORE_EBX_STATE CFI_PUSH (%ebx)
+	cmp	__x86_data_cache_size, %ecx
+# endif
+#endif
+
+	jae	L(128bytes_L2_normal)
+	subl	$128, %ecx
+L(128bytesormore_normal):
+	sub	$128, %ecx
+	movdqa	%xmm0, (%edx)
+	movdqa	%xmm0, 0x10(%edx)
+	movdqa	%xmm0, 0x20(%edx)
+	movdqa	%xmm0, 0x30(%edx)
+	movdqa	%xmm0, 0x40(%edx)
+	movdqa	%xmm0, 0x50(%edx)
+	movdqa	%xmm0, 0x60(%edx)
+	movdqa	%xmm0, 0x70(%edx)
+	lea	128(%edx), %edx
+	jb	L(128bytesless_normal)
+
+
+	sub	$128, %ecx
+	movdqa	%xmm0, (%edx)
+	movdqa	%xmm0, 0x10(%edx)
+	movdqa	%xmm0, 0x20(%edx)
+	movdqa	%xmm0, 0x30(%edx)
+	movdqa	%xmm0, 0x40(%edx)
+	movdqa	%xmm0, 0x50(%edx)
+	movdqa	%xmm0, 0x60(%edx)
+	movdqa	%xmm0, 0x70(%edx)
+	lea	128(%edx), %edx
+	jae	L(128bytesormore_normal)
+
+L(128bytesless_normal):
+	lea	128(%ecx), %ecx
+	add	%ecx, %edx
+	shr	$2, %ecx
+	BRANCH_TO_JMPTBL_ENTRY (L(table_16_128bytes))
+
+	ALIGN (4)
+L(128bytes_L2_normal):
+	prefetcht0	0x380(%edx)
+	prefetcht0	0x3c0(%edx)
+	sub	$128, %ecx
+	movdqa	%xmm0, (%edx)
+	movaps	%xmm0, 0x10(%edx)
+	movaps	%xmm0, 0x20(%edx)
+	movaps	%xmm0, 0x30(%edx)
+	movaps	%xmm0, 0x40(%edx)
+	movaps	%xmm0, 0x50(%edx)
+	movaps	%xmm0, 0x60(%edx)
+	movaps	%xmm0, 0x70(%edx)
+	add	$128, %edx
+	cmp	$128, %ecx 	
+	jae	L(128bytes_L2_normal)
+
+L(128bytesless_L2_normal):
+	add	%ecx, %edx
+	shr	$2, %ecx
+	BRANCH_TO_JMPTBL_ENTRY (L(table_16_128bytes))
+
+	RESTORE_EBX_STATE
+L(128bytesormore_nt_start):
+	sub	%ebx, %ecx
+	mov	%ebx, %eax
+	and	$0x7f, %eax
+	add	%eax, %ecx
+	movd	%xmm0, %eax
+	ALIGN (4)
+L(128bytesormore_shared_cache_loop):
+	prefetcht0	0x3c0(%edx)
+	prefetcht0	0x380(%edx)
+	sub	$0x80, %ebx
+	movdqa	%xmm0, (%edx)
+	movdqa	%xmm0, 0x10(%edx)
+	movdqa	%xmm0, 0x20(%edx)
+	movdqa	%xmm0, 0x30(%edx)
+	movdqa	%xmm0, 0x40(%edx)
+	movdqa	%xmm0, 0x50(%edx)
+	movdqa	%xmm0, 0x60(%edx)
+	movdqa	%xmm0, 0x70(%edx)
+	add	$0x80, %edx
+	cmp	$0x80, %ebx
+	jae	L(128bytesormore_shared_cache_loop)
+	cmp	$0x80, %ecx
+	jb	L(shared_cache_loop_end)
+
+	ALIGN (4)
+L(128bytesormore_nt):
+	sub	$0x80, %ecx
+	movntdq	%xmm0, (%edx)
+	movntdq	%xmm0, 0x10(%edx)
+	movntdq	%xmm0, 0x20(%edx)
+	movntdq	%xmm0, 0x30(%edx)
+	movntdq	%xmm0, 0x40(%edx)
+	movntdq	%xmm0, 0x50(%edx)
+	movntdq	%xmm0, 0x60(%edx)
+	movntdq	%xmm0, 0x70(%edx)
+	add	$0x80, %edx
+	cmp	$0x80, %ecx
+	jae	L(128bytesormore_nt)
+	sfence
+L(shared_cache_loop_end):
+#if defined DATA_CACHE_SIZE || !(defined SHARED || defined __PIC__)
+	POP (%ebx)
+#endif
+	add	%ecx, %edx
+	shr	$2, %ecx
+	BRANCH_TO_JMPTBL_ENTRY (L(table_16_128bytes))
+
+	.pushsection .rodata.sse2,"a",@progbits
+	ALIGN (2)
+L(table_16_128bytes):
+	.int	JMPTBL (L(aligned_16_0bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_4bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_8bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_12bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_16bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_20bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_24bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_28bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_32bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_36bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_40bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_44bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_48bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_52bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_56bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_60bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_64bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_68bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_72bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_76bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_80bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_84bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_88bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_92bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_96bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_100bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_104bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_108bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_112bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_116bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_120bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_124bytes), L(table_16_128bytes))
+	.popsection
+
+	ALIGN (4)
+L(aligned_16_112bytes):
+	movdqa	%xmm0, -112(%edx)
+L(aligned_16_96bytes):
+	movdqa	%xmm0, -96(%edx)
+L(aligned_16_80bytes):
+	movdqa	%xmm0, -80(%edx)
+L(aligned_16_64bytes):
+	movdqa	%xmm0, -64(%edx)
+L(aligned_16_48bytes):
+	movdqa	%xmm0, -48(%edx)
+L(aligned_16_32bytes):
+	movdqa	%xmm0, -32(%edx)
+L(aligned_16_16bytes):
+	movdqa	%xmm0, -16(%edx)
+L(aligned_16_0bytes):
+	SETRTNVAL
+	RETURN
+
+	ALIGN (4)
+L(aligned_16_116bytes):
+	movdqa	%xmm0, -116(%edx)
+L(aligned_16_100bytes):
+	movdqa	%xmm0, -100(%edx)
+L(aligned_16_84bytes):
+	movdqa	%xmm0, -84(%edx)
+L(aligned_16_68bytes):
+	movdqa	%xmm0, -68(%edx)
+L(aligned_16_52bytes):
+	movdqa	%xmm0, -52(%edx)
+L(aligned_16_36bytes):
+	movdqa	%xmm0, -36(%edx)
+L(aligned_16_20bytes):
+	movdqa	%xmm0, -20(%edx)
+L(aligned_16_4bytes):
+	movl	%eax, -4(%edx)
+	SETRTNVAL
+	RETURN
+
+	ALIGN (4)
+L(aligned_16_120bytes):
+	movdqa	%xmm0, -120(%edx)
+L(aligned_16_104bytes):
+	movdqa	%xmm0, -104(%edx)
+L(aligned_16_88bytes):
+	movdqa	%xmm0, -88(%edx)
+L(aligned_16_72bytes):
+	movdqa	%xmm0, -72(%edx)
+L(aligned_16_56bytes):
+	movdqa	%xmm0, -56(%edx)
+L(aligned_16_40bytes):
+	movdqa	%xmm0, -40(%edx)
+L(aligned_16_24bytes):
+	movdqa	%xmm0, -24(%edx)
+L(aligned_16_8bytes):
+	movq	%xmm0, -8(%edx)
+	SETRTNVAL
+	RETURN
+
+	ALIGN (4)
+L(aligned_16_124bytes):
+	movdqa	%xmm0, -124(%edx)
+L(aligned_16_108bytes):
+	movdqa	%xmm0, -108(%edx)
+L(aligned_16_92bytes):
+	movdqa	%xmm0, -92(%edx)
+L(aligned_16_76bytes):
+	movdqa	%xmm0, -76(%edx)
+L(aligned_16_60bytes):
+	movdqa	%xmm0, -60(%edx)
+L(aligned_16_44bytes):
+	movdqa	%xmm0, -44(%edx)
+L(aligned_16_28bytes):
+	movdqa	%xmm0, -28(%edx)
+L(aligned_16_12bytes):
+	movq	%xmm0, -12(%edx)
+	movl	%eax, -4(%edx)
+	SETRTNVAL
+	RETURN
+
+END (sse2_memset32_atom)
diff --git a/package/utils/adbd/src/libcutils/arch-x86_64/android_memset16.S b/package/utils/adbd/src/libcutils/arch-x86_64/android_memset16.S
new file mode 100644
index 0000000..cb6d4a3
--- /dev/null
+++ b/package/utils/adbd/src/libcutils/arch-x86_64/android_memset16.S
@@ -0,0 +1,565 @@
+/*
+ * Copyright (C) 2014 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 "cache.h"
+
+#ifndef MEMSET
+# define MEMSET		android_memset16
+#endif
+
+#ifndef L
+# define L(label)	.L##label
+#endif
+
+#ifndef ALIGN
+# define ALIGN(n)	.p2align n
+#endif
+
+#ifndef cfi_startproc
+# define cfi_startproc			.cfi_startproc
+#endif
+
+#ifndef cfi_endproc
+# define cfi_endproc			.cfi_endproc
+#endif
+
+#ifndef ENTRY
+# define ENTRY(name)			\
+	.type name,  @function; 	\
+	.globl name;			\
+	.p2align 4;			\
+name:					\
+	cfi_startproc
+#endif
+
+#ifndef END
+# define END(name)			\
+	cfi_endproc;			\
+	.size name, .-name
+#endif
+
+#define JMPTBL(I, B)	I - B
+
+/* Branch to an entry in a jump table.  TABLE is a jump table with
+   relative offsets.  INDEX is a register contains the index into the
+   jump table.  SCALE is the scale of INDEX.  */
+#define BRANCH_TO_JMPTBL_ENTRY(TABLE, INDEX, SCALE) \
+	lea    TABLE(%rip), %r11;						\
+	movslq (%r11, INDEX, SCALE), INDEX;				\
+	lea    (%r11, INDEX), INDEX;					\
+	jmp    *INDEX
+
+	.section .text.sse2,"ax",@progbits
+	ALIGN (4)
+ENTRY (MEMSET)	// Address in rdi
+	shr    $1, %rdx			// Count in rdx
+	movzwl %si, %ecx
+	/* Fill the whole ECX with pattern.  */
+	shl    $16, %esi
+	or     %esi, %ecx		// Pattern in ecx
+
+	cmp    $32, %rdx
+	jae    L(32wordsormore)
+
+L(write_less32words):
+	lea    (%rdi, %rdx, 2), %rdi
+	BRANCH_TO_JMPTBL_ENTRY (L(table_less32words), %rdx, 4)
+
+	.pushsection .rodata.sse2,"a",@progbits
+	ALIGN (2)
+L(table_less32words):
+	.int	JMPTBL (L(write_0words), L(table_less32words))
+	.int	JMPTBL (L(write_1words), L(table_less32words))
+	.int	JMPTBL (L(write_2words), L(table_less32words))
+	.int	JMPTBL (L(write_3words), L(table_less32words))
+	.int	JMPTBL (L(write_4words), L(table_less32words))
+	.int	JMPTBL (L(write_5words), L(table_less32words))
+	.int	JMPTBL (L(write_6words), L(table_less32words))
+	.int	JMPTBL (L(write_7words), L(table_less32words))
+	.int	JMPTBL (L(write_8words), L(table_less32words))
+	.int	JMPTBL (L(write_9words), L(table_less32words))
+	.int	JMPTBL (L(write_10words), L(table_less32words))
+	.int	JMPTBL (L(write_11words), L(table_less32words))
+	.int	JMPTBL (L(write_12words), L(table_less32words))
+	.int	JMPTBL (L(write_13words), L(table_less32words))
+	.int	JMPTBL (L(write_14words), L(table_less32words))
+	.int	JMPTBL (L(write_15words), L(table_less32words))
+	.int	JMPTBL (L(write_16words), L(table_less32words))
+	.int	JMPTBL (L(write_17words), L(table_less32words))
+	.int	JMPTBL (L(write_18words), L(table_less32words))
+	.int	JMPTBL (L(write_19words), L(table_less32words))
+	.int	JMPTBL (L(write_20words), L(table_less32words))
+	.int	JMPTBL (L(write_21words), L(table_less32words))
+	.int	JMPTBL (L(write_22words), L(table_less32words))
+	.int	JMPTBL (L(write_23words), L(table_less32words))
+	.int	JMPTBL (L(write_24words), L(table_less32words))
+	.int	JMPTBL (L(write_25words), L(table_less32words))
+	.int	JMPTBL (L(write_26words), L(table_less32words))
+	.int	JMPTBL (L(write_27words), L(table_less32words))
+	.int	JMPTBL (L(write_28words), L(table_less32words))
+	.int	JMPTBL (L(write_29words), L(table_less32words))
+	.int	JMPTBL (L(write_30words), L(table_less32words))
+	.int	JMPTBL (L(write_31words), L(table_less32words))
+	.popsection
+
+	ALIGN (4)
+L(write_28words):
+	movl   %ecx, -56(%rdi)
+	movl   %ecx, -52(%rdi)
+L(write_24words):
+	movl   %ecx, -48(%rdi)
+	movl   %ecx, -44(%rdi)
+L(write_20words):
+	movl   %ecx, -40(%rdi)
+	movl   %ecx, -36(%rdi)
+L(write_16words):
+	movl   %ecx, -32(%rdi)
+	movl   %ecx, -28(%rdi)
+L(write_12words):
+	movl   %ecx, -24(%rdi)
+	movl   %ecx, -20(%rdi)
+L(write_8words):
+	movl   %ecx, -16(%rdi)
+	movl   %ecx, -12(%rdi)
+L(write_4words):
+	movl   %ecx, -8(%rdi)
+	movl   %ecx, -4(%rdi)
+L(write_0words):
+	ret
+
+	ALIGN (4)
+L(write_29words):
+	movl   %ecx, -58(%rdi)
+	movl   %ecx, -54(%rdi)
+L(write_25words):
+	movl   %ecx, -50(%rdi)
+	movl   %ecx, -46(%rdi)
+L(write_21words):
+	movl   %ecx, -42(%rdi)
+	movl   %ecx, -38(%rdi)
+L(write_17words):
+	movl   %ecx, -34(%rdi)
+	movl   %ecx, -30(%rdi)
+L(write_13words):
+	movl   %ecx, -26(%rdi)
+	movl   %ecx, -22(%rdi)
+L(write_9words):
+	movl   %ecx, -18(%rdi)
+	movl   %ecx, -14(%rdi)
+L(write_5words):
+	movl   %ecx, -10(%rdi)
+	movl   %ecx, -6(%rdi)
+L(write_1words):
+	mov	%cx, -2(%rdi)
+	ret
+
+	ALIGN (4)
+L(write_30words):
+	movl   %ecx, -60(%rdi)
+	movl   %ecx, -56(%rdi)
+L(write_26words):
+	movl   %ecx, -52(%rdi)
+	movl   %ecx, -48(%rdi)
+L(write_22words):
+	movl   %ecx, -44(%rdi)
+	movl   %ecx, -40(%rdi)
+L(write_18words):
+	movl   %ecx, -36(%rdi)
+	movl   %ecx, -32(%rdi)
+L(write_14words):
+	movl   %ecx, -28(%rdi)
+	movl   %ecx, -24(%rdi)
+L(write_10words):
+	movl   %ecx, -20(%rdi)
+	movl   %ecx, -16(%rdi)
+L(write_6words):
+	movl   %ecx, -12(%rdi)
+	movl   %ecx, -8(%rdi)
+L(write_2words):
+	movl   %ecx, -4(%rdi)
+	ret
+
+	ALIGN (4)
+L(write_31words):
+	movl   %ecx, -62(%rdi)
+	movl   %ecx, -58(%rdi)
+L(write_27words):
+	movl   %ecx, -54(%rdi)
+	movl   %ecx, -50(%rdi)
+L(write_23words):
+	movl   %ecx, -46(%rdi)
+	movl   %ecx, -42(%rdi)
+L(write_19words):
+	movl   %ecx, -38(%rdi)
+	movl   %ecx, -34(%rdi)
+L(write_15words):
+	movl   %ecx, -30(%rdi)
+	movl   %ecx, -26(%rdi)
+L(write_11words):
+	movl   %ecx, -22(%rdi)
+	movl   %ecx, -18(%rdi)
+L(write_7words):
+	movl   %ecx, -14(%rdi)
+	movl   %ecx, -10(%rdi)
+L(write_3words):
+	movl   %ecx, -6(%rdi)
+	movw   %cx, -2(%rdi)
+	ret
+
+	ALIGN (4)
+L(32wordsormore):
+	shl    $1, %rdx
+	test   $0x01, %edi
+	jz     L(aligned2bytes)
+	mov    %ecx, (%rdi)
+	mov    %ecx, -4(%rdi, %rdx)
+	sub    $2, %rdx
+	add    $1, %rdi
+	rol    $8, %ecx
+L(aligned2bytes):
+	/* Fill xmm0 with the pattern.  */
+	movd   %ecx, %xmm0
+	pshufd $0, %xmm0, %xmm0
+
+	testl  $0xf, %edi
+	jz     L(aligned_16)
+/* RDX > 32 and RDI is not 16 byte aligned.  */
+	movdqu %xmm0, (%rdi)
+	mov    %rdi, %rsi
+	and    $-16, %rdi
+	add    $16, %rdi
+	sub    %rdi, %rsi
+	add    %rsi, %rdx
+
+	ALIGN (4)
+L(aligned_16):
+	cmp    $128, %rdx
+	jge    L(128bytesormore)
+
+L(aligned_16_less128bytes):
+	add    %rdx, %rdi
+	shr    $1, %rdx
+	BRANCH_TO_JMPTBL_ENTRY (L(table_16_128bytes), %rdx, 4)
+
+	ALIGN (4)
+L(128bytesormore):
+	cmp    $SHARED_CACHE_SIZE, %rdx
+	jg     L(128bytesormore_nt)
+
+L(128bytesormore_normal):
+	sub    $128, %rdx
+	movdqa %xmm0, (%rdi)
+	movdqa %xmm0, 0x10(%rdi)
+	movdqa %xmm0, 0x20(%rdi)
+	movdqa %xmm0, 0x30(%rdi)
+	movdqa %xmm0, 0x40(%rdi)
+	movdqa %xmm0, 0x50(%rdi)
+	movdqa %xmm0, 0x60(%rdi)
+	movdqa %xmm0, 0x70(%rdi)
+	lea    128(%rdi), %rdi
+	cmp    $128, %rdx
+	jl     L(128bytesless_normal)
+
+	sub    $128, %rdx
+	movdqa %xmm0, (%rdi)
+	movdqa %xmm0, 0x10(%rdi)
+	movdqa %xmm0, 0x20(%rdi)
+	movdqa %xmm0, 0x30(%rdi)
+	movdqa %xmm0, 0x40(%rdi)
+	movdqa %xmm0, 0x50(%rdi)
+	movdqa %xmm0, 0x60(%rdi)
+	movdqa %xmm0, 0x70(%rdi)
+	lea    128(%rdi), %rdi
+	cmp    $128, %rdx
+	jl     L(128bytesless_normal)
+
+	sub    $128, %rdx
+	movdqa %xmm0, (%rdi)
+	movdqa %xmm0, 0x10(%rdi)
+	movdqa %xmm0, 0x20(%rdi)
+	movdqa %xmm0, 0x30(%rdi)
+	movdqa %xmm0, 0x40(%rdi)
+	movdqa %xmm0, 0x50(%rdi)
+	movdqa %xmm0, 0x60(%rdi)
+	movdqa %xmm0, 0x70(%rdi)
+	lea    128(%rdi), %rdi
+	cmp    $128, %rdx
+	jl     L(128bytesless_normal)
+
+	sub    $128, %rdx
+	movdqa %xmm0, (%rdi)
+	movdqa %xmm0, 0x10(%rdi)
+	movdqa %xmm0, 0x20(%rdi)
+	movdqa %xmm0, 0x30(%rdi)
+	movdqa %xmm0, 0x40(%rdi)
+	movdqa %xmm0, 0x50(%rdi)
+	movdqa %xmm0, 0x60(%rdi)
+	movdqa %xmm0, 0x70(%rdi)
+	lea    128(%rdi), %rdi
+	cmp    $128, %rdx
+	jge    L(128bytesormore_normal)
+
+L(128bytesless_normal):
+	add    %rdx, %rdi
+	shr    $1, %rdx
+	BRANCH_TO_JMPTBL_ENTRY (L(table_16_128bytes), %rdx, 4)
+
+	ALIGN (4)
+L(128bytesormore_nt):
+	sub    $128, %rdx
+	movntdq %xmm0, (%rdi)
+	movntdq %xmm0, 0x10(%rdi)
+	movntdq %xmm0, 0x20(%rdi)
+	movntdq %xmm0, 0x30(%rdi)
+	movntdq %xmm0, 0x40(%rdi)
+	movntdq %xmm0, 0x50(%rdi)
+	movntdq %xmm0, 0x60(%rdi)
+	movntdq %xmm0, 0x70(%rdi)
+	lea    128(%rdi), %rdi
+	cmp    $128, %rdx
+	jge    L(128bytesormore_nt)
+
+	sfence
+	add    %rdx, %rdi
+	shr    $1, %rdx
+	BRANCH_TO_JMPTBL_ENTRY (L(table_16_128bytes), %rdx, 4)
+
+	.pushsection .rodata.sse2,"a",@progbits
+	ALIGN (2)
+L(table_16_128bytes):
+	.int	JMPTBL (L(aligned_16_0bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_2bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_4bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_6bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_8bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_10bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_12bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_14bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_16bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_18bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_20bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_22bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_24bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_26bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_28bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_30bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_32bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_34bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_36bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_38bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_40bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_42bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_44bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_46bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_48bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_50bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_52bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_54bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_56bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_58bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_60bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_62bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_64bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_66bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_68bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_70bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_72bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_74bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_76bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_78bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_80bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_82bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_84bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_86bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_88bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_90bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_92bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_94bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_96bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_98bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_100bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_102bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_104bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_106bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_108bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_110bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_112bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_114bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_116bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_118bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_120bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_122bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_124bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_126bytes), L(table_16_128bytes))
+	.popsection
+
+	ALIGN (4)
+L(aligned_16_112bytes):
+	movdqa %xmm0, -112(%rdi)
+L(aligned_16_96bytes):
+	movdqa %xmm0, -96(%rdi)
+L(aligned_16_80bytes):
+	movdqa %xmm0, -80(%rdi)
+L(aligned_16_64bytes):
+	movdqa %xmm0, -64(%rdi)
+L(aligned_16_48bytes):
+	movdqa %xmm0, -48(%rdi)
+L(aligned_16_32bytes):
+	movdqa %xmm0, -32(%rdi)
+L(aligned_16_16bytes):
+	movdqa %xmm0, -16(%rdi)
+L(aligned_16_0bytes):
+	ret
+
+	ALIGN (4)
+L(aligned_16_114bytes):
+	movdqa %xmm0, -114(%rdi)
+L(aligned_16_98bytes):
+	movdqa %xmm0, -98(%rdi)
+L(aligned_16_82bytes):
+	movdqa %xmm0, -82(%rdi)
+L(aligned_16_66bytes):
+	movdqa %xmm0, -66(%rdi)
+L(aligned_16_50bytes):
+	movdqa %xmm0, -50(%rdi)
+L(aligned_16_34bytes):
+	movdqa %xmm0, -34(%rdi)
+L(aligned_16_18bytes):
+	movdqa %xmm0, -18(%rdi)
+L(aligned_16_2bytes):
+	movw   %cx, -2(%rdi)
+	ret
+
+	ALIGN (4)
+L(aligned_16_116bytes):
+	movdqa %xmm0, -116(%rdi)
+L(aligned_16_100bytes):
+	movdqa %xmm0, -100(%rdi)
+L(aligned_16_84bytes):
+	movdqa %xmm0, -84(%rdi)
+L(aligned_16_68bytes):
+	movdqa %xmm0, -68(%rdi)
+L(aligned_16_52bytes):
+	movdqa %xmm0, -52(%rdi)
+L(aligned_16_36bytes):
+	movdqa %xmm0, -36(%rdi)
+L(aligned_16_20bytes):
+	movdqa %xmm0, -20(%rdi)
+L(aligned_16_4bytes):
+	movl   %ecx, -4(%rdi)
+	ret
+
+	ALIGN (4)
+L(aligned_16_118bytes):
+	movdqa %xmm0, -118(%rdi)
+L(aligned_16_102bytes):
+	movdqa %xmm0, -102(%rdi)
+L(aligned_16_86bytes):
+	movdqa %xmm0, -86(%rdi)
+L(aligned_16_70bytes):
+	movdqa %xmm0, -70(%rdi)
+L(aligned_16_54bytes):
+	movdqa %xmm0, -54(%rdi)
+L(aligned_16_38bytes):
+	movdqa %xmm0, -38(%rdi)
+L(aligned_16_22bytes):
+	movdqa %xmm0, -22(%rdi)
+L(aligned_16_6bytes):
+	movl   %ecx, -6(%rdi)
+	movw   %cx, -2(%rdi)
+	ret
+
+	ALIGN (4)
+L(aligned_16_120bytes):
+	movdqa %xmm0, -120(%rdi)
+L(aligned_16_104bytes):
+	movdqa %xmm0, -104(%rdi)
+L(aligned_16_88bytes):
+	movdqa %xmm0, -88(%rdi)
+L(aligned_16_72bytes):
+	movdqa %xmm0, -72(%rdi)
+L(aligned_16_56bytes):
+	movdqa %xmm0, -56(%rdi)
+L(aligned_16_40bytes):
+	movdqa %xmm0, -40(%rdi)
+L(aligned_16_24bytes):
+	movdqa %xmm0, -24(%rdi)
+L(aligned_16_8bytes):
+	movq   %xmm0, -8(%rdi)
+	ret
+
+	ALIGN (4)
+L(aligned_16_122bytes):
+	movdqa %xmm0, -122(%rdi)
+L(aligned_16_106bytes):
+	movdqa %xmm0, -106(%rdi)
+L(aligned_16_90bytes):
+	movdqa %xmm0, -90(%rdi)
+L(aligned_16_74bytes):
+	movdqa %xmm0, -74(%rdi)
+L(aligned_16_58bytes):
+	movdqa %xmm0, -58(%rdi)
+L(aligned_16_42bytes):
+	movdqa %xmm0, -42(%rdi)
+L(aligned_16_26bytes):
+	movdqa %xmm0, -26(%rdi)
+L(aligned_16_10bytes):
+	movq   %xmm0, -10(%rdi)
+	movw   %cx, -2(%rdi)
+	ret
+
+	ALIGN (4)
+L(aligned_16_124bytes):
+	movdqa %xmm0, -124(%rdi)
+L(aligned_16_108bytes):
+	movdqa %xmm0, -108(%rdi)
+L(aligned_16_92bytes):
+	movdqa %xmm0, -92(%rdi)
+L(aligned_16_76bytes):
+	movdqa %xmm0, -76(%rdi)
+L(aligned_16_60bytes):
+	movdqa %xmm0, -60(%rdi)
+L(aligned_16_44bytes):
+	movdqa %xmm0, -44(%rdi)
+L(aligned_16_28bytes):
+	movdqa %xmm0, -28(%rdi)
+L(aligned_16_12bytes):
+	movq   %xmm0, -12(%rdi)
+	movl   %ecx, -4(%rdi)
+	ret
+
+	ALIGN (4)
+L(aligned_16_126bytes):
+	movdqa %xmm0, -126(%rdi)
+L(aligned_16_110bytes):
+	movdqa %xmm0, -110(%rdi)
+L(aligned_16_94bytes):
+	movdqa %xmm0, -94(%rdi)
+L(aligned_16_78bytes):
+	movdqa %xmm0, -78(%rdi)
+L(aligned_16_62bytes):
+	movdqa %xmm0, -62(%rdi)
+L(aligned_16_46bytes):
+	movdqa %xmm0, -46(%rdi)
+L(aligned_16_30bytes):
+	movdqa %xmm0, -30(%rdi)
+L(aligned_16_14bytes):
+	movq   %xmm0, -14(%rdi)
+	movl   %ecx, -6(%rdi)
+	movw   %cx, -2(%rdi)
+	ret
+
+END (MEMSET)
diff --git a/package/utils/adbd/src/libcutils/arch-x86_64/android_memset16_SSE2-atom.S b/package/utils/adbd/src/libcutils/arch-x86_64/android_memset16_SSE2-atom.S
new file mode 100644
index 0000000..48a10ed
--- /dev/null
+++ b/package/utils/adbd/src/libcutils/arch-x86_64/android_memset16_SSE2-atom.S
@@ -0,0 +1,564 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+/*
+ * Contributed by: Intel Corporation
+ */
+
+#include "cache.h"
+
+#ifndef L
+# define L(label)	.L##label
+#endif
+
+#ifndef ALIGN
+# define ALIGN(n)	.p2align n
+#endif
+
+#ifndef cfi_startproc
+# define cfi_startproc			.cfi_startproc
+#endif
+
+#ifndef cfi_endproc
+# define cfi_endproc			.cfi_endproc
+#endif
+
+#ifndef ENTRY
+# define ENTRY(name)			\
+	.type name,  @function; 	\
+	.globl name;			\
+	.p2align 4;			\
+name:					\
+	cfi_startproc
+#endif
+
+#ifndef END
+# define END(name)			\
+	cfi_endproc;			\
+	.size name, .-name
+#endif
+
+#define JMPTBL(I, B)	I - B
+
+/* Branch to an entry in a jump table.  TABLE is a jump table with
+   relative offsets.  INDEX is a register contains the index into the
+   jump table.  SCALE is the scale of INDEX.  */
+#define BRANCH_TO_JMPTBL_ENTRY(TABLE, INDEX, SCALE) \
+	lea    TABLE(%rip), %r11;						\
+	movslq (%r11, INDEX, SCALE), INDEX;				\
+	lea    (%r11, INDEX), INDEX;					\
+	jmp    *INDEX
+
+	.section .text.sse2,"ax",@progbits
+	ALIGN (4)
+ENTRY (android_memset16)	// Address in rdi
+	shr    $1, %rdx			// Count in rdx
+	movzwl %si, %ecx
+	/* Fill the whole ECX with pattern.  */
+	shl    $16, %esi
+	or     %esi, %ecx		// Pattern in ecx
+
+	cmp    $32, %rdx
+	jae    L(32wordsormore)
+
+L(write_less32words):
+	lea    (%rdi, %rdx, 2), %rdi
+	BRANCH_TO_JMPTBL_ENTRY (L(table_less32words), %rdx, 4)
+
+	.pushsection .rodata.sse2,"a",@progbits
+	ALIGN (2)
+L(table_less32words):
+	.int	JMPTBL (L(write_0words), L(table_less32words))
+	.int	JMPTBL (L(write_1words), L(table_less32words))
+	.int	JMPTBL (L(write_2words), L(table_less32words))
+	.int	JMPTBL (L(write_3words), L(table_less32words))
+	.int	JMPTBL (L(write_4words), L(table_less32words))
+	.int	JMPTBL (L(write_5words), L(table_less32words))
+	.int	JMPTBL (L(write_6words), L(table_less32words))
+	.int	JMPTBL (L(write_7words), L(table_less32words))
+	.int	JMPTBL (L(write_8words), L(table_less32words))
+	.int	JMPTBL (L(write_9words), L(table_less32words))
+	.int	JMPTBL (L(write_10words), L(table_less32words))
+	.int	JMPTBL (L(write_11words), L(table_less32words))
+	.int	JMPTBL (L(write_12words), L(table_less32words))
+	.int	JMPTBL (L(write_13words), L(table_less32words))
+	.int	JMPTBL (L(write_14words), L(table_less32words))
+	.int	JMPTBL (L(write_15words), L(table_less32words))
+	.int	JMPTBL (L(write_16words), L(table_less32words))
+	.int	JMPTBL (L(write_17words), L(table_less32words))
+	.int	JMPTBL (L(write_18words), L(table_less32words))
+	.int	JMPTBL (L(write_19words), L(table_less32words))
+	.int	JMPTBL (L(write_20words), L(table_less32words))
+	.int	JMPTBL (L(write_21words), L(table_less32words))
+	.int	JMPTBL (L(write_22words), L(table_less32words))
+	.int	JMPTBL (L(write_23words), L(table_less32words))
+	.int	JMPTBL (L(write_24words), L(table_less32words))
+	.int	JMPTBL (L(write_25words), L(table_less32words))
+	.int	JMPTBL (L(write_26words), L(table_less32words))
+	.int	JMPTBL (L(write_27words), L(table_less32words))
+	.int	JMPTBL (L(write_28words), L(table_less32words))
+	.int	JMPTBL (L(write_29words), L(table_less32words))
+	.int	JMPTBL (L(write_30words), L(table_less32words))
+	.int	JMPTBL (L(write_31words), L(table_less32words))
+	.popsection
+
+	ALIGN (4)
+L(write_28words):
+	movl   %ecx, -56(%rdi)
+	movl   %ecx, -52(%rdi)
+L(write_24words):
+	movl   %ecx, -48(%rdi)
+	movl   %ecx, -44(%rdi)
+L(write_20words):
+	movl   %ecx, -40(%rdi)
+	movl   %ecx, -36(%rdi)
+L(write_16words):
+	movl   %ecx, -32(%rdi)
+	movl   %ecx, -28(%rdi)
+L(write_12words):
+	movl   %ecx, -24(%rdi)
+	movl   %ecx, -20(%rdi)
+L(write_8words):
+	movl   %ecx, -16(%rdi)
+	movl   %ecx, -12(%rdi)
+L(write_4words):
+	movl   %ecx, -8(%rdi)
+	movl   %ecx, -4(%rdi)
+L(write_0words):
+	ret
+
+	ALIGN (4)
+L(write_29words):
+	movl   %ecx, -58(%rdi)
+	movl   %ecx, -54(%rdi)
+L(write_25words):
+	movl   %ecx, -50(%rdi)
+	movl   %ecx, -46(%rdi)
+L(write_21words):
+	movl   %ecx, -42(%rdi)
+	movl   %ecx, -38(%rdi)
+L(write_17words):
+	movl   %ecx, -34(%rdi)
+	movl   %ecx, -30(%rdi)
+L(write_13words):
+	movl   %ecx, -26(%rdi)
+	movl   %ecx, -22(%rdi)
+L(write_9words):
+	movl   %ecx, -18(%rdi)
+	movl   %ecx, -14(%rdi)
+L(write_5words):
+	movl   %ecx, -10(%rdi)
+	movl   %ecx, -6(%rdi)
+L(write_1words):
+	mov	%cx, -2(%rdi)
+	ret
+
+	ALIGN (4)
+L(write_30words):
+	movl   %ecx, -60(%rdi)
+	movl   %ecx, -56(%rdi)
+L(write_26words):
+	movl   %ecx, -52(%rdi)
+	movl   %ecx, -48(%rdi)
+L(write_22words):
+	movl   %ecx, -44(%rdi)
+	movl   %ecx, -40(%rdi)
+L(write_18words):
+	movl   %ecx, -36(%rdi)
+	movl   %ecx, -32(%rdi)
+L(write_14words):
+	movl   %ecx, -28(%rdi)
+	movl   %ecx, -24(%rdi)
+L(write_10words):
+	movl   %ecx, -20(%rdi)
+	movl   %ecx, -16(%rdi)
+L(write_6words):
+	movl   %ecx, -12(%rdi)
+	movl   %ecx, -8(%rdi)
+L(write_2words):
+	movl   %ecx, -4(%rdi)
+	ret
+
+	ALIGN (4)
+L(write_31words):
+	movl   %ecx, -62(%rdi)
+	movl   %ecx, -58(%rdi)
+L(write_27words):
+	movl   %ecx, -54(%rdi)
+	movl   %ecx, -50(%rdi)
+L(write_23words):
+	movl   %ecx, -46(%rdi)
+	movl   %ecx, -42(%rdi)
+L(write_19words):
+	movl   %ecx, -38(%rdi)
+	movl   %ecx, -34(%rdi)
+L(write_15words):
+	movl   %ecx, -30(%rdi)
+	movl   %ecx, -26(%rdi)
+L(write_11words):
+	movl   %ecx, -22(%rdi)
+	movl   %ecx, -18(%rdi)
+L(write_7words):
+	movl   %ecx, -14(%rdi)
+	movl   %ecx, -10(%rdi)
+L(write_3words):
+	movl   %ecx, -6(%rdi)
+	movw   %cx, -2(%rdi)
+	ret
+
+	ALIGN (4)
+L(32wordsormore):
+	shl    $1, %rdx
+	test   $0x01, %edi
+	jz     L(aligned2bytes)
+	mov    %ecx, (%rdi)
+	mov    %ecx, -4(%rdi, %rdx)
+	sub    $2, %rdx
+	add    $1, %rdi
+	rol    $8, %ecx
+L(aligned2bytes):
+	/* Fill xmm0 with the pattern.  */
+	movd   %ecx, %xmm0
+	pshufd $0, %xmm0, %xmm0
+
+	testl  $0xf, %edi
+	jz     L(aligned_16)
+/* RDX > 32 and RDI is not 16 byte aligned.  */
+	movdqu %xmm0, (%rdi)
+	mov    %rdi, %rsi
+	and    $-16, %rdi
+	add    $16, %rdi
+	sub    %rdi, %rsi
+	add    %rsi, %rdx
+
+	ALIGN (4)
+L(aligned_16):
+	cmp    $128, %rdx
+	jge    L(128bytesormore)
+
+L(aligned_16_less128bytes):
+	add    %rdx, %rdi
+	shr    $1, %rdx
+	BRANCH_TO_JMPTBL_ENTRY (L(table_16_128bytes), %rdx, 4)
+
+	ALIGN (4)
+L(128bytesormore):
+	cmp    $SHARED_CACHE_SIZE, %rdx
+	jg     L(128bytesormore_nt)
+
+L(128bytesormore_normal):
+	sub    $128, %rdx
+	movdqa %xmm0, (%rdi)
+	movdqa %xmm0, 0x10(%rdi)
+	movdqa %xmm0, 0x20(%rdi)
+	movdqa %xmm0, 0x30(%rdi)
+	movdqa %xmm0, 0x40(%rdi)
+	movdqa %xmm0, 0x50(%rdi)
+	movdqa %xmm0, 0x60(%rdi)
+	movdqa %xmm0, 0x70(%rdi)
+	lea    128(%rdi), %rdi
+	cmp    $128, %rdx
+	jl     L(128bytesless_normal)
+
+	sub    $128, %rdx
+	movdqa %xmm0, (%rdi)
+	movdqa %xmm0, 0x10(%rdi)
+	movdqa %xmm0, 0x20(%rdi)
+	movdqa %xmm0, 0x30(%rdi)
+	movdqa %xmm0, 0x40(%rdi)
+	movdqa %xmm0, 0x50(%rdi)
+	movdqa %xmm0, 0x60(%rdi)
+	movdqa %xmm0, 0x70(%rdi)
+	lea    128(%rdi), %rdi
+	cmp    $128, %rdx
+	jl     L(128bytesless_normal)
+
+	sub    $128, %rdx
+	movdqa %xmm0, (%rdi)
+	movdqa %xmm0, 0x10(%rdi)
+	movdqa %xmm0, 0x20(%rdi)
+	movdqa %xmm0, 0x30(%rdi)
+	movdqa %xmm0, 0x40(%rdi)
+	movdqa %xmm0, 0x50(%rdi)
+	movdqa %xmm0, 0x60(%rdi)
+	movdqa %xmm0, 0x70(%rdi)
+	lea    128(%rdi), %rdi
+	cmp    $128, %rdx
+	jl     L(128bytesless_normal)
+
+	sub    $128, %rdx
+	movdqa %xmm0, (%rdi)
+	movdqa %xmm0, 0x10(%rdi)
+	movdqa %xmm0, 0x20(%rdi)
+	movdqa %xmm0, 0x30(%rdi)
+	movdqa %xmm0, 0x40(%rdi)
+	movdqa %xmm0, 0x50(%rdi)
+	movdqa %xmm0, 0x60(%rdi)
+	movdqa %xmm0, 0x70(%rdi)
+	lea    128(%rdi), %rdi
+	cmp    $128, %rdx
+	jge    L(128bytesormore_normal)
+
+L(128bytesless_normal):
+	add    %rdx, %rdi
+	shr    $1, %rdx
+	BRANCH_TO_JMPTBL_ENTRY (L(table_16_128bytes), %rdx, 4)
+
+	ALIGN (4)
+L(128bytesormore_nt):
+	sub    $128, %rdx
+	movntdq %xmm0, (%rdi)
+	movntdq %xmm0, 0x10(%rdi)
+	movntdq %xmm0, 0x20(%rdi)
+	movntdq %xmm0, 0x30(%rdi)
+	movntdq %xmm0, 0x40(%rdi)
+	movntdq %xmm0, 0x50(%rdi)
+	movntdq %xmm0, 0x60(%rdi)
+	movntdq %xmm0, 0x70(%rdi)
+	lea    128(%rdi), %rdi
+	cmp    $128, %rdx
+	jge    L(128bytesormore_nt)
+
+	sfence
+	add    %rdx, %rdi
+	shr    $1, %rdx
+	BRANCH_TO_JMPTBL_ENTRY (L(table_16_128bytes), %rdx, 4)
+
+	.pushsection .rodata.sse2,"a",@progbits
+	ALIGN (2)
+L(table_16_128bytes):
+	.int	JMPTBL (L(aligned_16_0bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_2bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_4bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_6bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_8bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_10bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_12bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_14bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_16bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_18bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_20bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_22bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_24bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_26bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_28bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_30bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_32bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_34bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_36bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_38bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_40bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_42bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_44bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_46bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_48bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_50bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_52bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_54bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_56bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_58bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_60bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_62bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_64bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_66bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_68bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_70bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_72bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_74bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_76bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_78bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_80bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_82bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_84bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_86bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_88bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_90bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_92bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_94bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_96bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_98bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_100bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_102bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_104bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_106bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_108bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_110bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_112bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_114bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_116bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_118bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_120bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_122bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_124bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_126bytes), L(table_16_128bytes))
+	.popsection
+
+	ALIGN (4)
+L(aligned_16_112bytes):
+	movdqa %xmm0, -112(%rdi)
+L(aligned_16_96bytes):
+	movdqa %xmm0, -96(%rdi)
+L(aligned_16_80bytes):
+	movdqa %xmm0, -80(%rdi)
+L(aligned_16_64bytes):
+	movdqa %xmm0, -64(%rdi)
+L(aligned_16_48bytes):
+	movdqa %xmm0, -48(%rdi)
+L(aligned_16_32bytes):
+	movdqa %xmm0, -32(%rdi)
+L(aligned_16_16bytes):
+	movdqa %xmm0, -16(%rdi)
+L(aligned_16_0bytes):
+	ret
+
+	ALIGN (4)
+L(aligned_16_114bytes):
+	movdqa %xmm0, -114(%rdi)
+L(aligned_16_98bytes):
+	movdqa %xmm0, -98(%rdi)
+L(aligned_16_82bytes):
+	movdqa %xmm0, -82(%rdi)
+L(aligned_16_66bytes):
+	movdqa %xmm0, -66(%rdi)
+L(aligned_16_50bytes):
+	movdqa %xmm0, -50(%rdi)
+L(aligned_16_34bytes):
+	movdqa %xmm0, -34(%rdi)
+L(aligned_16_18bytes):
+	movdqa %xmm0, -18(%rdi)
+L(aligned_16_2bytes):
+	movw   %cx, -2(%rdi)
+	ret
+
+	ALIGN (4)
+L(aligned_16_116bytes):
+	movdqa %xmm0, -116(%rdi)
+L(aligned_16_100bytes):
+	movdqa %xmm0, -100(%rdi)
+L(aligned_16_84bytes):
+	movdqa %xmm0, -84(%rdi)
+L(aligned_16_68bytes):
+	movdqa %xmm0, -68(%rdi)
+L(aligned_16_52bytes):
+	movdqa %xmm0, -52(%rdi)
+L(aligned_16_36bytes):
+	movdqa %xmm0, -36(%rdi)
+L(aligned_16_20bytes):
+	movdqa %xmm0, -20(%rdi)
+L(aligned_16_4bytes):
+	movl   %ecx, -4(%rdi)
+	ret
+
+	ALIGN (4)
+L(aligned_16_118bytes):
+	movdqa %xmm0, -118(%rdi)
+L(aligned_16_102bytes):
+	movdqa %xmm0, -102(%rdi)
+L(aligned_16_86bytes):
+	movdqa %xmm0, -86(%rdi)
+L(aligned_16_70bytes):
+	movdqa %xmm0, -70(%rdi)
+L(aligned_16_54bytes):
+	movdqa %xmm0, -54(%rdi)
+L(aligned_16_38bytes):
+	movdqa %xmm0, -38(%rdi)
+L(aligned_16_22bytes):
+	movdqa %xmm0, -22(%rdi)
+L(aligned_16_6bytes):
+	movl   %ecx, -6(%rdi)
+	movw   %cx, -2(%rdi)
+	ret
+
+	ALIGN (4)
+L(aligned_16_120bytes):
+	movdqa %xmm0, -120(%rdi)
+L(aligned_16_104bytes):
+	movdqa %xmm0, -104(%rdi)
+L(aligned_16_88bytes):
+	movdqa %xmm0, -88(%rdi)
+L(aligned_16_72bytes):
+	movdqa %xmm0, -72(%rdi)
+L(aligned_16_56bytes):
+	movdqa %xmm0, -56(%rdi)
+L(aligned_16_40bytes):
+	movdqa %xmm0, -40(%rdi)
+L(aligned_16_24bytes):
+	movdqa %xmm0, -24(%rdi)
+L(aligned_16_8bytes):
+	movq   %xmm0, -8(%rdi)
+	ret
+
+	ALIGN (4)
+L(aligned_16_122bytes):
+	movdqa %xmm0, -122(%rdi)
+L(aligned_16_106bytes):
+	movdqa %xmm0, -106(%rdi)
+L(aligned_16_90bytes):
+	movdqa %xmm0, -90(%rdi)
+L(aligned_16_74bytes):
+	movdqa %xmm0, -74(%rdi)
+L(aligned_16_58bytes):
+	movdqa %xmm0, -58(%rdi)
+L(aligned_16_42bytes):
+	movdqa %xmm0, -42(%rdi)
+L(aligned_16_26bytes):
+	movdqa %xmm0, -26(%rdi)
+L(aligned_16_10bytes):
+	movq   %xmm0, -10(%rdi)
+	movw   %cx, -2(%rdi)
+	ret
+
+	ALIGN (4)
+L(aligned_16_124bytes):
+	movdqa %xmm0, -124(%rdi)
+L(aligned_16_108bytes):
+	movdqa %xmm0, -108(%rdi)
+L(aligned_16_92bytes):
+	movdqa %xmm0, -92(%rdi)
+L(aligned_16_76bytes):
+	movdqa %xmm0, -76(%rdi)
+L(aligned_16_60bytes):
+	movdqa %xmm0, -60(%rdi)
+L(aligned_16_44bytes):
+	movdqa %xmm0, -44(%rdi)
+L(aligned_16_28bytes):
+	movdqa %xmm0, -28(%rdi)
+L(aligned_16_12bytes):
+	movq   %xmm0, -12(%rdi)
+	movl   %ecx, -4(%rdi)
+	ret
+
+	ALIGN (4)
+L(aligned_16_126bytes):
+	movdqa %xmm0, -126(%rdi)
+L(aligned_16_110bytes):
+	movdqa %xmm0, -110(%rdi)
+L(aligned_16_94bytes):
+	movdqa %xmm0, -94(%rdi)
+L(aligned_16_78bytes):
+	movdqa %xmm0, -78(%rdi)
+L(aligned_16_62bytes):
+	movdqa %xmm0, -62(%rdi)
+L(aligned_16_46bytes):
+	movdqa %xmm0, -46(%rdi)
+L(aligned_16_30bytes):
+	movdqa %xmm0, -30(%rdi)
+L(aligned_16_14bytes):
+	movq   %xmm0, -14(%rdi)
+	movl   %ecx, -6(%rdi)
+	movw   %cx, -2(%rdi)
+	ret
+
+END (android_memset16)
diff --git a/package/utils/adbd/src/libcutils/arch-x86_64/android_memset32.S b/package/utils/adbd/src/libcutils/arch-x86_64/android_memset32.S
new file mode 100644
index 0000000..1514aa2
--- /dev/null
+++ b/package/utils/adbd/src/libcutils/arch-x86_64/android_memset32.S
@@ -0,0 +1,373 @@
+/*
+ * Copyright (C) 2014 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 "cache.h"
+
+#ifndef MEMSET
+# define MEMSET		android_memset32
+#endif
+
+#ifndef L
+# define L(label)	.L##label
+#endif
+
+#ifndef ALIGN
+# define ALIGN(n)	.p2align n
+#endif
+
+#ifndef cfi_startproc
+# define cfi_startproc			.cfi_startproc
+#endif
+
+#ifndef cfi_endproc
+# define cfi_endproc			.cfi_endproc
+#endif
+
+#ifndef ENTRY
+# define ENTRY(name)			\
+	.type name,  @function; 	\
+	.globl name;			\
+	.p2align 4;			\
+name:					\
+	cfi_startproc
+#endif
+
+#ifndef END
+# define END(name)			\
+	cfi_endproc;			\
+	.size name, .-name
+#endif
+
+#define JMPTBL(I, B)	I - B
+
+/* Branch to an entry in a jump table.  TABLE is a jump table with
+   relative offsets.  INDEX is a register contains the index into the
+   jump table.  SCALE is the scale of INDEX.  */
+#define BRANCH_TO_JMPTBL_ENTRY(TABLE, INDEX, SCALE) \
+	lea    TABLE(%rip), %r11;						\
+	movslq (%r11, INDEX, SCALE), INDEX;				\
+	lea    (%r11, INDEX), INDEX;					\
+	jmp    *INDEX
+
+	.section .text.sse2,"ax",@progbits
+	ALIGN (4)
+ENTRY (MEMSET)	// Address in rdi
+	shr    $2, %rdx			// Count in rdx
+	movl   %esi, %ecx		// Pattern in ecx
+
+	cmp    $16, %rdx
+	jae    L(16dbwordsormore)
+
+L(write_less16dbwords):
+	lea    (%rdi, %rdx, 4), %rdi
+	BRANCH_TO_JMPTBL_ENTRY (L(table_less16dbwords), %rdx, 4)
+
+	.pushsection .rodata.sse2,"a",@progbits
+	ALIGN (2)
+L(table_less16dbwords):
+	.int	JMPTBL (L(write_0dbwords), L(table_less16dbwords))
+	.int	JMPTBL (L(write_1dbwords), L(table_less16dbwords))
+	.int	JMPTBL (L(write_2dbwords), L(table_less16dbwords))
+	.int	JMPTBL (L(write_3dbwords), L(table_less16dbwords))
+	.int	JMPTBL (L(write_4dbwords), L(table_less16dbwords))
+	.int	JMPTBL (L(write_5dbwords), L(table_less16dbwords))
+	.int	JMPTBL (L(write_6dbwords), L(table_less16dbwords))
+	.int	JMPTBL (L(write_7dbwords), L(table_less16dbwords))
+	.int	JMPTBL (L(write_8dbwords), L(table_less16dbwords))
+	.int	JMPTBL (L(write_9dbwords), L(table_less16dbwords))
+	.int	JMPTBL (L(write_10dbwords), L(table_less16dbwords))
+	.int	JMPTBL (L(write_11dbwords), L(table_less16dbwords))
+	.int	JMPTBL (L(write_12dbwords), L(table_less16dbwords))
+	.int	JMPTBL (L(write_13dbwords), L(table_less16dbwords))
+	.int	JMPTBL (L(write_14dbwords), L(table_less16dbwords))
+	.int	JMPTBL (L(write_15dbwords), L(table_less16dbwords))
+	.popsection
+
+	ALIGN (4)
+L(write_15dbwords):
+	movl   %ecx, -60(%rdi)
+L(write_14dbwords):
+	movl   %ecx, -56(%rdi)
+L(write_13dbwords):
+	movl   %ecx, -52(%rdi)
+L(write_12dbwords):
+	movl   %ecx, -48(%rdi)
+L(write_11dbwords):
+	movl   %ecx, -44(%rdi)
+L(write_10dbwords):
+	movl   %ecx, -40(%rdi)
+L(write_9dbwords):
+	movl   %ecx, -36(%rdi)
+L(write_8dbwords):
+	movl   %ecx, -32(%rdi)
+L(write_7dbwords):
+	movl   %ecx, -28(%rdi)
+L(write_6dbwords):
+	movl   %ecx, -24(%rdi)
+L(write_5dbwords):
+	movl   %ecx, -20(%rdi)
+L(write_4dbwords):
+	movl   %ecx, -16(%rdi)
+L(write_3dbwords):
+	movl   %ecx, -12(%rdi)
+L(write_2dbwords):
+	movl   %ecx, -8(%rdi)
+L(write_1dbwords):
+	movl   %ecx, -4(%rdi)
+L(write_0dbwords):
+	ret
+
+	ALIGN (4)
+L(16dbwordsormore):
+	test   $3, %edi
+	jz     L(aligned4bytes)
+	mov    %ecx, (%rdi)
+	mov    %ecx, -4(%rdi, %rdx, 4)
+	sub    $1, %rdx
+	rol    $24, %ecx
+	add    $1, %rdi
+	test   $3, %edi
+	jz     L(aligned4bytes)
+	ror    $8, %ecx
+	add    $1, %rdi
+	test   $3, %edi
+	jz     L(aligned4bytes)
+	ror    $8, %ecx
+	add    $1, %rdi
+L(aligned4bytes):
+	shl    $2, %rdx
+
+	/* Fill xmm0 with the pattern.  */
+	movd   %ecx, %xmm0
+	pshufd $0, %xmm0, %xmm0
+
+	testl  $0xf, %edi
+	jz     L(aligned_16)
+/* RDX > 32 and RDI is not 16 byte aligned.  */
+	movdqu %xmm0, (%rdi)
+	mov    %rdi, %rsi
+	and    $-16, %rdi
+	add    $16, %rdi
+	sub    %rdi, %rsi
+	add    %rsi, %rdx
+
+	ALIGN (4)
+L(aligned_16):
+	cmp    $128, %rdx
+	jge    L(128bytesormore)
+
+L(aligned_16_less128bytes):
+	add    %rdx, %rdi
+	shr    $2, %rdx
+	BRANCH_TO_JMPTBL_ENTRY (L(table_16_128bytes), %rdx, 4)
+
+	ALIGN (4)
+L(128bytesormore):
+	cmp    $SHARED_CACHE_SIZE, %rdx
+	jg     L(128bytesormore_nt)
+
+L(128bytesormore_normal):
+	sub    $128, %rdx
+	movdqa %xmm0, (%rdi)
+	movdqa %xmm0, 0x10(%rdi)
+	movdqa %xmm0, 0x20(%rdi)
+	movdqa %xmm0, 0x30(%rdi)
+	movdqa %xmm0, 0x40(%rdi)
+	movdqa %xmm0, 0x50(%rdi)
+	movdqa %xmm0, 0x60(%rdi)
+	movdqa %xmm0, 0x70(%rdi)
+	lea    128(%rdi), %rdi
+	cmp    $128, %rdx
+	jl     L(128bytesless_normal)
+
+	sub    $128, %rdx
+	movdqa %xmm0, (%rdi)
+	movdqa %xmm0, 0x10(%rdi)
+	movdqa %xmm0, 0x20(%rdi)
+	movdqa %xmm0, 0x30(%rdi)
+	movdqa %xmm0, 0x40(%rdi)
+	movdqa %xmm0, 0x50(%rdi)
+	movdqa %xmm0, 0x60(%rdi)
+	movdqa %xmm0, 0x70(%rdi)
+	lea    128(%rdi), %rdi
+	cmp    $128, %rdx
+	jl     L(128bytesless_normal)
+
+	sub    $128, %rdx
+	movdqa %xmm0, (%rdi)
+	movdqa %xmm0, 0x10(%rdi)
+	movdqa %xmm0, 0x20(%rdi)
+	movdqa %xmm0, 0x30(%rdi)
+	movdqa %xmm0, 0x40(%rdi)
+	movdqa %xmm0, 0x50(%rdi)
+	movdqa %xmm0, 0x60(%rdi)
+	movdqa %xmm0, 0x70(%rdi)
+	lea    128(%rdi), %rdi
+	cmp    $128, %rdx
+	jl     L(128bytesless_normal)
+
+	sub    $128, %rdx
+	movdqa %xmm0, (%rdi)
+	movdqa %xmm0, 0x10(%rdi)
+	movdqa %xmm0, 0x20(%rdi)
+	movdqa %xmm0, 0x30(%rdi)
+	movdqa %xmm0, 0x40(%rdi)
+	movdqa %xmm0, 0x50(%rdi)
+	movdqa %xmm0, 0x60(%rdi)
+	movdqa %xmm0, 0x70(%rdi)
+	lea    128(%rdi), %rdi
+	cmp    $128, %rdx
+	jge    L(128bytesormore_normal)
+
+L(128bytesless_normal):
+	add    %rdx, %rdi
+	shr    $2, %rdx
+	BRANCH_TO_JMPTBL_ENTRY (L(table_16_128bytes), %rdx, 4)
+
+	ALIGN (4)
+L(128bytesormore_nt):
+	sub    $128, %rdx
+	movntdq %xmm0, (%rdi)
+	movntdq %xmm0, 0x10(%rdi)
+	movntdq %xmm0, 0x20(%rdi)
+	movntdq %xmm0, 0x30(%rdi)
+	movntdq %xmm0, 0x40(%rdi)
+	movntdq %xmm0, 0x50(%rdi)
+	movntdq %xmm0, 0x60(%rdi)
+	movntdq %xmm0, 0x70(%rdi)
+	lea    128(%rdi), %rdi
+	cmp    $128, %rdx
+	jge    L(128bytesormore_nt)
+
+	sfence
+	add    %rdx, %rdi
+	shr    $2, %rdx
+	BRANCH_TO_JMPTBL_ENTRY (L(table_16_128bytes), %rdx, 4)
+
+	.pushsection .rodata.sse2,"a",@progbits
+	ALIGN (2)
+L(table_16_128bytes):
+	.int	JMPTBL (L(aligned_16_0bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_4bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_8bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_12bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_16bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_20bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_24bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_28bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_32bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_36bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_40bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_44bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_48bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_52bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_56bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_60bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_64bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_68bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_72bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_76bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_80bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_84bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_88bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_92bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_96bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_100bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_104bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_108bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_112bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_116bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_120bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_124bytes), L(table_16_128bytes))
+	.popsection
+
+	ALIGN (4)
+L(aligned_16_112bytes):
+	movdqa	%xmm0, -112(%rdi)
+L(aligned_16_96bytes):
+	movdqa	%xmm0, -96(%rdi)
+L(aligned_16_80bytes):
+	movdqa	%xmm0, -80(%rdi)
+L(aligned_16_64bytes):
+	movdqa	%xmm0, -64(%rdi)
+L(aligned_16_48bytes):
+	movdqa	%xmm0, -48(%rdi)
+L(aligned_16_32bytes):
+	movdqa	%xmm0, -32(%rdi)
+L(aligned_16_16bytes):
+	movdqa	%xmm0, -16(%rdi)
+L(aligned_16_0bytes):
+	ret
+
+	ALIGN (4)
+L(aligned_16_116bytes):
+	movdqa	%xmm0, -116(%rdi)
+L(aligned_16_100bytes):
+	movdqa	%xmm0, -100(%rdi)
+L(aligned_16_84bytes):
+	movdqa	%xmm0, -84(%rdi)
+L(aligned_16_68bytes):
+	movdqa	%xmm0, -68(%rdi)
+L(aligned_16_52bytes):
+	movdqa	%xmm0, -52(%rdi)
+L(aligned_16_36bytes):
+	movdqa	%xmm0, -36(%rdi)
+L(aligned_16_20bytes):
+	movdqa	%xmm0, -20(%rdi)
+L(aligned_16_4bytes):
+	movl	%ecx, -4(%rdi)
+	ret
+
+	ALIGN (4)
+L(aligned_16_120bytes):
+	movdqa	%xmm0, -120(%rdi)
+L(aligned_16_104bytes):
+	movdqa	%xmm0, -104(%rdi)
+L(aligned_16_88bytes):
+	movdqa	%xmm0, -88(%rdi)
+L(aligned_16_72bytes):
+	movdqa	%xmm0, -72(%rdi)
+L(aligned_16_56bytes):
+	movdqa	%xmm0, -56(%rdi)
+L(aligned_16_40bytes):
+	movdqa	%xmm0, -40(%rdi)
+L(aligned_16_24bytes):
+	movdqa	%xmm0, -24(%rdi)
+L(aligned_16_8bytes):
+	movq	%xmm0, -8(%rdi)
+	ret
+
+	ALIGN (4)
+L(aligned_16_124bytes):
+	movdqa	%xmm0, -124(%rdi)
+L(aligned_16_108bytes):
+	movdqa	%xmm0, -108(%rdi)
+L(aligned_16_92bytes):
+	movdqa	%xmm0, -92(%rdi)
+L(aligned_16_76bytes):
+	movdqa	%xmm0, -76(%rdi)
+L(aligned_16_60bytes):
+	movdqa	%xmm0, -60(%rdi)
+L(aligned_16_44bytes):
+	movdqa	%xmm0, -44(%rdi)
+L(aligned_16_28bytes):
+	movdqa	%xmm0, -28(%rdi)
+L(aligned_16_12bytes):
+	movq	%xmm0, -12(%rdi)
+	movl	%ecx, -4(%rdi)
+	ret
+
+END (MEMSET)
diff --git a/package/utils/adbd/src/libcutils/arch-x86_64/android_memset32_SSE2-atom.S b/package/utils/adbd/src/libcutils/arch-x86_64/android_memset32_SSE2-atom.S
new file mode 100644
index 0000000..4bdea8e
--- /dev/null
+++ b/package/utils/adbd/src/libcutils/arch-x86_64/android_memset32_SSE2-atom.S
@@ -0,0 +1,372 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+/*
+ * Contributed by: Intel Corporation
+ */
+
+#include "cache.h"
+
+#ifndef L
+# define L(label)	.L##label
+#endif
+
+#ifndef ALIGN
+# define ALIGN(n)	.p2align n
+#endif
+
+#ifndef cfi_startproc
+# define cfi_startproc			.cfi_startproc
+#endif
+
+#ifndef cfi_endproc
+# define cfi_endproc			.cfi_endproc
+#endif
+
+#ifndef ENTRY
+# define ENTRY(name)			\
+	.type name,  @function; 	\
+	.globl name;			\
+	.p2align 4;			\
+name:					\
+	cfi_startproc
+#endif
+
+#ifndef END
+# define END(name)			\
+	cfi_endproc;			\
+	.size name, .-name
+#endif
+
+#define JMPTBL(I, B)	I - B
+
+/* Branch to an entry in a jump table.  TABLE is a jump table with
+   relative offsets.  INDEX is a register contains the index into the
+   jump table.  SCALE is the scale of INDEX.  */
+#define BRANCH_TO_JMPTBL_ENTRY(TABLE, INDEX, SCALE) \
+	lea    TABLE(%rip), %r11;						\
+	movslq (%r11, INDEX, SCALE), INDEX;				\
+	lea    (%r11, INDEX), INDEX;					\
+	jmp    *INDEX
+
+	.section .text.sse2,"ax",@progbits
+	ALIGN (4)
+ENTRY (android_memset32)	// Address in rdi
+	shr    $2, %rdx			// Count in rdx
+	movl   %esi, %ecx		// Pattern in ecx
+
+	cmp    $16, %rdx
+	jae    L(16dbwordsormore)
+
+L(write_less16dbwords):
+	lea    (%rdi, %rdx, 4), %rdi
+	BRANCH_TO_JMPTBL_ENTRY (L(table_less16dbwords), %rdx, 4)
+
+	.pushsection .rodata.sse2,"a",@progbits
+	ALIGN (2)
+L(table_less16dbwords):
+	.int	JMPTBL (L(write_0dbwords), L(table_less16dbwords))
+	.int	JMPTBL (L(write_1dbwords), L(table_less16dbwords))
+	.int	JMPTBL (L(write_2dbwords), L(table_less16dbwords))
+	.int	JMPTBL (L(write_3dbwords), L(table_less16dbwords))
+	.int	JMPTBL (L(write_4dbwords), L(table_less16dbwords))
+	.int	JMPTBL (L(write_5dbwords), L(table_less16dbwords))
+	.int	JMPTBL (L(write_6dbwords), L(table_less16dbwords))
+	.int	JMPTBL (L(write_7dbwords), L(table_less16dbwords))
+	.int	JMPTBL (L(write_8dbwords), L(table_less16dbwords))
+	.int	JMPTBL (L(write_9dbwords), L(table_less16dbwords))
+	.int	JMPTBL (L(write_10dbwords), L(table_less16dbwords))
+	.int	JMPTBL (L(write_11dbwords), L(table_less16dbwords))
+	.int	JMPTBL (L(write_12dbwords), L(table_less16dbwords))
+	.int	JMPTBL (L(write_13dbwords), L(table_less16dbwords))
+	.int	JMPTBL (L(write_14dbwords), L(table_less16dbwords))
+	.int	JMPTBL (L(write_15dbwords), L(table_less16dbwords))
+	.popsection
+
+	ALIGN (4)
+L(write_15dbwords):
+	movl   %ecx, -60(%rdi)
+L(write_14dbwords):
+	movl   %ecx, -56(%rdi)
+L(write_13dbwords):
+	movl   %ecx, -52(%rdi)
+L(write_12dbwords):
+	movl   %ecx, -48(%rdi)
+L(write_11dbwords):
+	movl   %ecx, -44(%rdi)
+L(write_10dbwords):
+	movl   %ecx, -40(%rdi)
+L(write_9dbwords):
+	movl   %ecx, -36(%rdi)
+L(write_8dbwords):
+	movl   %ecx, -32(%rdi)
+L(write_7dbwords):
+	movl   %ecx, -28(%rdi)
+L(write_6dbwords):
+	movl   %ecx, -24(%rdi)
+L(write_5dbwords):
+	movl   %ecx, -20(%rdi)
+L(write_4dbwords):
+	movl   %ecx, -16(%rdi)
+L(write_3dbwords):
+	movl   %ecx, -12(%rdi)
+L(write_2dbwords):
+	movl   %ecx, -8(%rdi)
+L(write_1dbwords):
+	movl   %ecx, -4(%rdi)
+L(write_0dbwords):
+	ret
+
+	ALIGN (4)
+L(16dbwordsormore):
+	test   $3, %edi
+	jz     L(aligned4bytes)
+	mov    %ecx, (%rdi)
+	mov    %ecx, -4(%rdi, %rdx, 4)
+	sub    $1, %rdx
+	rol    $24, %ecx
+	add    $1, %rdi
+	test   $3, %edi
+	jz     L(aligned4bytes)
+	ror    $8, %ecx
+	add    $1, %rdi
+	test   $3, %edi
+	jz     L(aligned4bytes)
+	ror    $8, %ecx
+	add    $1, %rdi
+L(aligned4bytes):
+	shl    $2, %rdx
+
+	/* Fill xmm0 with the pattern.  */
+	movd   %ecx, %xmm0
+	pshufd $0, %xmm0, %xmm0
+
+	testl  $0xf, %edi
+	jz     L(aligned_16)
+/* RDX > 32 and RDI is not 16 byte aligned.  */
+	movdqu %xmm0, (%rdi)
+	mov    %rdi, %rsi
+	and    $-16, %rdi
+	add    $16, %rdi
+	sub    %rdi, %rsi
+	add    %rsi, %rdx
+
+	ALIGN (4)
+L(aligned_16):
+	cmp    $128, %rdx
+	jge    L(128bytesormore)
+
+L(aligned_16_less128bytes):
+	add    %rdx, %rdi
+	shr    $2, %rdx
+	BRANCH_TO_JMPTBL_ENTRY (L(table_16_128bytes), %rdx, 4)
+
+	ALIGN (4)
+L(128bytesormore):
+	cmp    $SHARED_CACHE_SIZE, %rdx
+	jg     L(128bytesormore_nt)
+
+L(128bytesormore_normal):
+	sub    $128, %rdx
+	movdqa %xmm0, (%rdi)
+	movdqa %xmm0, 0x10(%rdi)
+	movdqa %xmm0, 0x20(%rdi)
+	movdqa %xmm0, 0x30(%rdi)
+	movdqa %xmm0, 0x40(%rdi)
+	movdqa %xmm0, 0x50(%rdi)
+	movdqa %xmm0, 0x60(%rdi)
+	movdqa %xmm0, 0x70(%rdi)
+	lea    128(%rdi), %rdi
+	cmp    $128, %rdx
+	jl     L(128bytesless_normal)
+
+	sub    $128, %rdx
+	movdqa %xmm0, (%rdi)
+	movdqa %xmm0, 0x10(%rdi)
+	movdqa %xmm0, 0x20(%rdi)
+	movdqa %xmm0, 0x30(%rdi)
+	movdqa %xmm0, 0x40(%rdi)
+	movdqa %xmm0, 0x50(%rdi)
+	movdqa %xmm0, 0x60(%rdi)
+	movdqa %xmm0, 0x70(%rdi)
+	lea    128(%rdi), %rdi
+	cmp    $128, %rdx
+	jl     L(128bytesless_normal)
+
+	sub    $128, %rdx
+	movdqa %xmm0, (%rdi)
+	movdqa %xmm0, 0x10(%rdi)
+	movdqa %xmm0, 0x20(%rdi)
+	movdqa %xmm0, 0x30(%rdi)
+	movdqa %xmm0, 0x40(%rdi)
+	movdqa %xmm0, 0x50(%rdi)
+	movdqa %xmm0, 0x60(%rdi)
+	movdqa %xmm0, 0x70(%rdi)
+	lea    128(%rdi), %rdi
+	cmp    $128, %rdx
+	jl     L(128bytesless_normal)
+
+	sub    $128, %rdx
+	movdqa %xmm0, (%rdi)
+	movdqa %xmm0, 0x10(%rdi)
+	movdqa %xmm0, 0x20(%rdi)
+	movdqa %xmm0, 0x30(%rdi)
+	movdqa %xmm0, 0x40(%rdi)
+	movdqa %xmm0, 0x50(%rdi)
+	movdqa %xmm0, 0x60(%rdi)
+	movdqa %xmm0, 0x70(%rdi)
+	lea    128(%rdi), %rdi
+	cmp    $128, %rdx
+	jge    L(128bytesormore_normal)
+
+L(128bytesless_normal):
+	add    %rdx, %rdi
+	shr    $2, %rdx
+	BRANCH_TO_JMPTBL_ENTRY (L(table_16_128bytes), %rdx, 4)
+
+	ALIGN (4)
+L(128bytesormore_nt):
+	sub    $128, %rdx
+	movntdq %xmm0, (%rdi)
+	movntdq %xmm0, 0x10(%rdi)
+	movntdq %xmm0, 0x20(%rdi)
+	movntdq %xmm0, 0x30(%rdi)
+	movntdq %xmm0, 0x40(%rdi)
+	movntdq %xmm0, 0x50(%rdi)
+	movntdq %xmm0, 0x60(%rdi)
+	movntdq %xmm0, 0x70(%rdi)
+	lea    128(%rdi), %rdi
+	cmp    $128, %rdx
+	jge    L(128bytesormore_nt)
+
+	sfence
+	add    %rdx, %rdi
+	shr    $2, %rdx
+	BRANCH_TO_JMPTBL_ENTRY (L(table_16_128bytes), %rdx, 4)
+
+	.pushsection .rodata.sse2,"a",@progbits
+	ALIGN (2)
+L(table_16_128bytes):
+	.int	JMPTBL (L(aligned_16_0bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_4bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_8bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_12bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_16bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_20bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_24bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_28bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_32bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_36bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_40bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_44bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_48bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_52bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_56bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_60bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_64bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_68bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_72bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_76bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_80bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_84bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_88bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_92bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_96bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_100bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_104bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_108bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_112bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_116bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_120bytes), L(table_16_128bytes))
+	.int	JMPTBL (L(aligned_16_124bytes), L(table_16_128bytes))
+	.popsection
+
+	ALIGN (4)
+L(aligned_16_112bytes):
+	movdqa	%xmm0, -112(%rdi)
+L(aligned_16_96bytes):
+	movdqa	%xmm0, -96(%rdi)
+L(aligned_16_80bytes):
+	movdqa	%xmm0, -80(%rdi)
+L(aligned_16_64bytes):
+	movdqa	%xmm0, -64(%rdi)
+L(aligned_16_48bytes):
+	movdqa	%xmm0, -48(%rdi)
+L(aligned_16_32bytes):
+	movdqa	%xmm0, -32(%rdi)
+L(aligned_16_16bytes):
+	movdqa	%xmm0, -16(%rdi)
+L(aligned_16_0bytes):
+	ret
+
+	ALIGN (4)
+L(aligned_16_116bytes):
+	movdqa	%xmm0, -116(%rdi)
+L(aligned_16_100bytes):
+	movdqa	%xmm0, -100(%rdi)
+L(aligned_16_84bytes):
+	movdqa	%xmm0, -84(%rdi)
+L(aligned_16_68bytes):
+	movdqa	%xmm0, -68(%rdi)
+L(aligned_16_52bytes):
+	movdqa	%xmm0, -52(%rdi)
+L(aligned_16_36bytes):
+	movdqa	%xmm0, -36(%rdi)
+L(aligned_16_20bytes):
+	movdqa	%xmm0, -20(%rdi)
+L(aligned_16_4bytes):
+	movl	%ecx, -4(%rdi)
+	ret
+
+	ALIGN (4)
+L(aligned_16_120bytes):
+	movdqa	%xmm0, -120(%rdi)
+L(aligned_16_104bytes):
+	movdqa	%xmm0, -104(%rdi)
+L(aligned_16_88bytes):
+	movdqa	%xmm0, -88(%rdi)
+L(aligned_16_72bytes):
+	movdqa	%xmm0, -72(%rdi)
+L(aligned_16_56bytes):
+	movdqa	%xmm0, -56(%rdi)
+L(aligned_16_40bytes):
+	movdqa	%xmm0, -40(%rdi)
+L(aligned_16_24bytes):
+	movdqa	%xmm0, -24(%rdi)
+L(aligned_16_8bytes):
+	movq	%xmm0, -8(%rdi)
+	ret
+
+	ALIGN (4)
+L(aligned_16_124bytes):
+	movdqa	%xmm0, -124(%rdi)
+L(aligned_16_108bytes):
+	movdqa	%xmm0, -108(%rdi)
+L(aligned_16_92bytes):
+	movdqa	%xmm0, -92(%rdi)
+L(aligned_16_76bytes):
+	movdqa	%xmm0, -76(%rdi)
+L(aligned_16_60bytes):
+	movdqa	%xmm0, -60(%rdi)
+L(aligned_16_44bytes):
+	movdqa	%xmm0, -44(%rdi)
+L(aligned_16_28bytes):
+	movdqa	%xmm0, -28(%rdi)
+L(aligned_16_12bytes):
+	movq	%xmm0, -12(%rdi)
+	movl	%ecx, -4(%rdi)
+	ret
+
+END (android_memset32)
diff --git a/package/utils/adbd/src/libcutils/arch-x86_64/cache.h b/package/utils/adbd/src/libcutils/arch-x86_64/cache.h
new file mode 100644
index 0000000..ab5dd2f
--- /dev/null
+++ b/package/utils/adbd/src/libcutils/arch-x86_64/cache.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+/*
+ * Contributed by: Intel Corporation
+ */
+
+#if defined(__slm__)
+/* Values are optimized for Silvermont */
+#define SHARED_CACHE_SIZE	(1024*1024)			/* Silvermont L2 Cache */
+#define DATA_CACHE_SIZE		(24*1024)			/* Silvermont L1 Data Cache */
+#else
+/* Values are optimized for Atom */
+#define SHARED_CACHE_SIZE	(512*1024)			/* Atom L2 Cache */
+#define DATA_CACHE_SIZE		(24*1024)			/* Atom L1 Data Cache */
+#endif
+
+#define SHARED_CACHE_SIZE_HALF	(SHARED_CACHE_SIZE / 2)
+#define DATA_CACHE_SIZE_HALF	(DATA_CACHE_SIZE / 2)
diff --git a/package/utils/adbd/src/libcutils/ashmem-dev.c b/package/utils/adbd/src/libcutils/ashmem-dev.c
new file mode 100644
index 0000000..3089a94
--- /dev/null
+++ b/package/utils/adbd/src/libcutils/ashmem-dev.c
@@ -0,0 +1,90 @@
+/*
+ * 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.
+ */
+
+/*
+ * Implementation of the user-space ashmem API for devices, which have our
+ * ashmem-enabled kernel. See ashmem-sim.c for the "fake" tmp-based version,
+ * used by the simulator.
+ */
+
+#include <unistd.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+
+#include <linux/ashmem.h>
+#include <cutils/ashmem.h>
+
+#define ASHMEM_DEVICE	"/dev/ashmem"
+
+/*
+ * ashmem_create_region - creates a new ashmem region and returns the file
+ * descriptor, or <0 on error
+ *
+ * `name' is an optional label to give the region (visible in /proc/pid/maps)
+ * `size' is the size of the region, in page-aligned bytes
+ */
+int ashmem_create_region(const char *name, size_t size)
+{
+	int fd, ret;
+
+	fd = open(ASHMEM_DEVICE, O_RDWR);
+	if (fd < 0)
+		return fd;
+
+	if (name) {
+		char buf[ASHMEM_NAME_LEN] = {0};
+
+		strlcpy(buf, name, sizeof(buf));
+		ret = ioctl(fd, ASHMEM_SET_NAME, buf);
+		if (ret < 0)
+			goto error;
+	}
+
+	ret = ioctl(fd, ASHMEM_SET_SIZE, size);
+	if (ret < 0)
+		goto error;
+
+	return fd;
+
+error:
+	close(fd);
+	return ret;
+}
+
+int ashmem_set_prot_region(int fd, int prot)
+{
+	return ioctl(fd, ASHMEM_SET_PROT_MASK, prot);
+}
+
+int ashmem_pin_region(int fd, size_t offset, size_t len)
+{
+	struct ashmem_pin pin = { offset, len };
+	return ioctl(fd, ASHMEM_PIN, &pin);
+}
+
+int ashmem_unpin_region(int fd, size_t offset, size_t len)
+{
+	struct ashmem_pin pin = { offset, len };
+	return ioctl(fd, ASHMEM_UNPIN, &pin);
+}
+
+int ashmem_get_size_region(int fd)
+{
+  return ioctl(fd, ASHMEM_GET_SIZE, NULL);
+}
diff --git a/package/utils/adbd/src/libcutils/ashmem-host.c b/package/utils/adbd/src/libcutils/ashmem-host.c
new file mode 100644
index 0000000..4ac4f57
--- /dev/null
+++ b/package/utils/adbd/src/libcutils/ashmem-host.c
@@ -0,0 +1,120 @@
+/*
+ * 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.
+ */
+
+/*
+ * Implementation of the user-space ashmem API for the simulator, which lacks
+ * an ashmem-enabled kernel. See ashmem-dev.c for the real ashmem-based version.
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <pthread.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <cutils/ashmem.h>
+
+#ifndef __unused
+#define __unused __attribute__((__unused__))
+#endif
+
+static pthread_once_t seed_initialized = PTHREAD_ONCE_INIT;
+static void initialize_random() {
+    srand(time(NULL) + getpid());
+}
+
+int ashmem_create_region(const char *ignored __unused, size_t size)
+{
+    static const char txt[] = "abcdefghijklmnopqrstuvwxyz"
+            "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+    char name[64];
+    unsigned int retries = 0;
+    pid_t pid = getpid();
+    int fd;
+    if (pthread_once(&seed_initialized, &initialize_random) != 0) {
+        return -1;
+    }
+    do {
+        /* not beautiful, its just wolf-like loop unrolling */
+        snprintf(name, sizeof(name), "/tmp/android-ashmem-%d-%c%c%c%c%c%c%c%c",
+        pid,
+        txt[(int) ((sizeof(txt) - 1) * (rand() / (RAND_MAX + 1.0)))],
+        txt[(int) ((sizeof(txt) - 1) * (rand() / (RAND_MAX + 1.0)))],
+        txt[(int) ((sizeof(txt) - 1) * (rand() / (RAND_MAX + 1.0)))],
+        txt[(int) ((sizeof(txt) - 1) * (rand() / (RAND_MAX + 1.0)))],
+        txt[(int) ((sizeof(txt) - 1) * (rand() / (RAND_MAX + 1.0)))],
+        txt[(int) ((sizeof(txt) - 1) * (rand() / (RAND_MAX + 1.0)))],
+        txt[(int) ((sizeof(txt) - 1) * (rand() / (RAND_MAX + 1.0)))],
+        txt[(int) ((sizeof(txt) - 1) * (rand() / (RAND_MAX + 1.0)))]);
+
+        /* open O_EXCL & O_CREAT: we are either the sole owner or we fail */
+        fd = open(name, O_RDWR | O_CREAT | O_EXCL, 0600);
+        if (fd == -1) {
+            /* unlikely, but if we failed because `name' exists, retry */
+            if (errno != EEXIST || ++retries >= 6) {
+                return -1;
+            }
+        }
+    } while (fd == -1);
+    /* truncate the file to `len' bytes */
+    if (ftruncate(fd, size) != -1 && unlink(name) != -1) {
+        return fd;
+    }
+    close(fd);
+    return -1;
+}
+
+int ashmem_set_prot_region(int fd __unused, int prot __unused)
+{
+    return 0;
+}
+
+int ashmem_pin_region(int fd __unused, size_t offset __unused, size_t len __unused)
+{
+    return ASHMEM_NOT_PURGED;
+}
+
+int ashmem_unpin_region(int fd __unused, size_t offset __unused, size_t len __unused)
+{
+    return ASHMEM_IS_UNPINNED;
+}
+
+int ashmem_get_size_region(int fd)
+{
+    struct stat buf;
+    int result;
+
+    result = fstat(fd, &buf);
+    if (result == -1) {
+        return -1;
+    }
+
+    // Check if this is an "ashmem" region.
+    // TODO: This is very hacky, and can easily break. We need some reliable indicator.
+    if (!(buf.st_nlink == 0 && S_ISREG(buf.st_mode))) {
+        errno = ENOTTY;
+        return -1;
+    }
+
+    return (int)buf.st_size;    // TODO: care about overflow (> 2GB file)?
+}
diff --git a/package/utils/adbd/src/libcutils/atomic.c b/package/utils/adbd/src/libcutils/atomic.c
new file mode 100644
index 0000000..1484ef8
--- /dev/null
+++ b/package/utils/adbd/src/libcutils/atomic.c
@@ -0,0 +1,19 @@
+/*
+ * 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.
+ */
+
+#define ANDROID_ATOMIC_INLINE
+
+#include <cutils/atomic-inline.h>
diff --git a/package/utils/adbd/src/libcutils/config_utils.c b/package/utils/adbd/src/libcutils/config_utils.c
new file mode 100644
index 0000000..fc5ca78
--- /dev/null
+++ b/package/utils/adbd/src/libcutils/config_utils.c
@@ -0,0 +1,329 @@
+/*
+ * 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 <string.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <cutils/config_utils.h>
+#include <cutils/misc.h>
+
+cnode* config_node(const char *name, const char *value)
+{
+    cnode *node;
+
+    node = calloc(sizeof(cnode), 1);
+    if(node) {
+        node->name = name ? name : "";
+        node->value = value ? value : "";
+    }
+
+    return node;
+}
+
+cnode* config_find(cnode *root, const char *name)
+{
+    cnode *node, *match = NULL;
+
+    /* we walk the whole list, as we need to return the last (newest) entry */
+    for(node = root->first_child; node; node = node->next)
+        if(!strcmp(node->name, name))
+            match = node;
+
+    return match;
+}
+
+static cnode* _config_create(cnode *root, const char *name)
+{
+    cnode *node;
+
+    node = config_node(name, NULL);
+
+    if(root->last_child)
+        root->last_child->next = node;
+    else
+        root->first_child = node;
+
+    root->last_child = node;
+
+    return node;
+}
+
+int config_bool(cnode *root, const char *name, int _default)
+{
+    cnode *node;
+        
+    node = config_find(root, name);
+    if(!node)
+        return _default;
+
+    switch(node->value[0]) {
+    case 'y':
+    case 'Y':
+    case '1':
+        return 1;
+    default:
+        return 0;
+    }
+}
+
+const char* config_str(cnode *root, const char *name, const char *_default)
+{
+    cnode *node;
+
+    node = config_find(root, name);
+    if(!node)
+        return _default;
+    return node->value;
+}
+
+void config_set(cnode *root, const char *name, const char *value)
+{
+    cnode *node;
+
+    node = config_find(root, name);
+    if(node)
+        node->value = value;
+    else {
+        node = _config_create(root, name);
+        node->value = value;
+    }
+}
+
+#define T_EOF 0
+#define T_TEXT 1
+#define T_DOT 2
+#define T_OBRACE 3
+#define T_CBRACE 4
+
+typedef struct
+{
+    char *data;
+    char *text;
+    int len;
+    char next;
+} cstate;
+
+static int _lex(cstate *cs, int value)
+{
+    char c;
+    char *s;
+    char *data;
+
+    data = cs->data;
+
+    if(cs->next != 0) {
+        c = cs->next;
+        cs->next = 0;
+        goto got_c;
+    }
+
+restart:
+    for(;;) {
+        c = *data++;
+    got_c:
+        if(isspace(c))
+            continue;
+
+        switch(c) {
+        case 0:
+            return T_EOF;
+
+        case '#':
+            for(;;) {
+                switch(*data) {
+                case 0:
+                    cs->data = data;
+                    return T_EOF;
+                case '\n':
+                    cs->data = data + 1;
+                    goto restart;
+                default:
+                    data++;
+                }
+            }
+            break;
+            
+        case '.':
+            cs->data = data;
+            return T_DOT;
+
+        case '{':
+            cs->data = data;
+            return T_OBRACE;
+
+        case '}':
+            cs->data = data;
+            return T_CBRACE;
+
+        default:
+            s = data - 1;
+
+            if(value) {
+                for(;;) {
+                    if(*data == 0) {
+                        cs->data = data;
+                        break;
+                    }
+                    if(*data == '\n') {
+                        cs->data = data + 1;
+                        *data-- = 0;
+                        break;
+                    }
+                    data++;
+                }
+
+                    /* strip trailing whitespace */
+                while(data > s){
+                    if(!isspace(*data)) break;
+                    *data-- = 0;
+                }
+
+                goto got_text;                
+            } else {
+                for(;;) {
+                    if(isspace(*data)) {
+                        *data = 0;
+                        cs->data = data + 1;
+                        goto got_text;
+                    }
+                    switch(*data) {
+                    case 0:
+                        cs->data = data;
+                        goto got_text;
+                    case '.':
+                    case '{':
+                    case '}':
+                        cs->next = *data;
+                        *data = 0;
+                        cs->data = data + 1;
+                        goto got_text;
+                    default:
+                        data++;
+                    }
+                }
+            }
+        }
+    }
+
+got_text:
+    cs->text = s;
+    return T_TEXT;
+}
+
+#if 0
+char *TOKENNAMES[] = { "EOF", "TEXT", "DOT", "OBRACE", "CBRACE" };
+
+static int lex(cstate *cs, int value)
+{
+    int tok = _lex(cs, value);
+    printf("TOKEN(%d) %s %s\n", value, TOKENNAMES[tok],
+           tok == T_TEXT ? cs->text : "");
+    return tok;
+}
+#else
+#define lex(cs,v) _lex(cs,v)
+#endif
+
+static int parse_expr(cstate *cs, cnode *node);
+
+static int parse_block(cstate *cs, cnode *node)
+{
+    for(;;){
+        switch(lex(cs, 0)){
+        case T_TEXT:
+            if(parse_expr(cs, node)) return -1;
+            continue;
+
+        case T_CBRACE:
+            return 0;
+
+        default:
+            return -1;
+        }
+    }
+}
+
+static int parse_expr(cstate *cs, cnode *root)
+{
+    cnode *node;
+
+        /* last token was T_TEXT */
+    node = config_find(root, cs->text);
+    if(!node || *node->value)
+        node = _config_create(root, cs->text);
+
+    for(;;) {
+        switch(lex(cs, 1)) {
+        case T_DOT:
+            if(lex(cs, 0) != T_TEXT)
+                return -1;
+            node = _config_create(node, cs->text);
+            continue;
+
+        case T_TEXT:
+            node->value = cs->text;
+            return 0;
+
+        case T_OBRACE:
+            return parse_block(cs, node);
+
+        default:
+            return -1;
+        }
+    }
+}
+
+void config_load(cnode *root, char *data)
+{
+    if(data != 0) {
+        cstate cs;
+        cs.data = data;
+        cs.next = 0;
+
+        for(;;) {
+            switch(lex(&cs, 0)) {
+            case T_TEXT:
+                if(parse_expr(&cs, root))
+                    return;
+                break;
+            default:
+                return;
+            }
+        }
+    }
+}
+
+void config_load_file(cnode *root, const char *fn)
+{
+    char *data;
+    data = load_file(fn, 0);
+    config_load(root, data);
+}
+
+void config_free(cnode *root)
+{
+    cnode *cur = root->first_child;
+
+    while (cur) {
+        cnode *prev = cur;
+        config_free(cur);
+        cur = cur->next;
+        free(prev);
+    }
+}
diff --git a/package/utils/adbd/src/libcutils/cpu_info.c b/package/utils/adbd/src/libcutils/cpu_info.c
new file mode 100644
index 0000000..21fa1dc
--- /dev/null
+++ b/package/utils/adbd/src/libcutils/cpu_info.c
@@ -0,0 +1,82 @@
+/*
+** Copyright 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 <cutils/cpu_info.h>
+
+// we cache the serial number here.
+// this is also used as a fgets() line buffer when we are reading /proc/cpuinfo
+static char serial_number[100] = { 0 };
+
+extern const char* get_cpu_serial_number(void)
+{
+    if (serial_number[0] == 0)
+    {
+        FILE* file;
+        char* chp, *end;
+        char* whitespace;
+        
+        // read serial number from /proc/cpuinfo
+        file = fopen("proc/cpuinfo", "r");
+        if (! file)
+            return NULL;
+        
+        while ((chp = fgets(serial_number, sizeof(serial_number), file)) != NULL)
+        {
+            // look for something like "Serial          : 999206122a03591c"
+
+            if (strncmp(chp, "Serial", 6) != 0)
+                continue;
+            
+            chp = strchr(chp, ':');
+            if (!chp)
+                continue;
+                
+             // skip colon and whitespace
+            while ( *(++chp) == ' ') {}
+            
+            // truncate trailing whitespace
+            end = chp;
+            while (*end && *end != ' ' && *end != '\t' && *end != '\n' && *end != '\r')
+                ++end;
+            *end = 0; 
+            
+            whitespace = strchr(chp, ' ');
+            if (whitespace)
+                *whitespace = 0;
+            whitespace = strchr(chp, '\t');
+            if (whitespace)
+                *whitespace = 0;
+            whitespace = strchr(chp, '\r');
+            if (whitespace)
+                *whitespace = 0;
+            whitespace = strchr(chp, '\n');
+            if (whitespace)
+                *whitespace = 0;
+
+            // shift serial number to beginning of the buffer
+            memmove(serial_number, chp, strlen(chp) + 1);
+            break;
+        }
+        
+        fclose(file);
+    }
+
+    return (serial_number[0] ? serial_number : NULL);
+}
diff --git a/package/utils/adbd/src/libcutils/debugger.c b/package/utils/adbd/src/libcutils/debugger.c
new file mode 100644
index 0000000..056de5d
--- /dev/null
+++ b/package/utils/adbd/src/libcutils/debugger.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2012 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 <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <cutils/debugger.h>
+#include <cutils/sockets.h>
+
+int dump_tombstone(pid_t tid, char* pathbuf, size_t pathlen) {
+    int s = socket_local_client(DEBUGGER_SOCKET_NAME,
+            ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
+    if (s < 0) {
+        return -1;
+    }
+
+    debugger_msg_t msg;
+    memset(&msg, 0, sizeof(msg));
+    msg.tid = tid;
+    msg.action = DEBUGGER_ACTION_DUMP_TOMBSTONE;
+
+    int result = 0;
+    if (TEMP_FAILURE_RETRY(write(s, &msg, sizeof(msg))) != sizeof(msg)) {
+        result = -1;
+    } else {
+        char ack;
+        if (TEMP_FAILURE_RETRY(read(s, &ack, 1)) != 1) {
+            result = -1;
+        } else {
+            if (pathbuf && pathlen) {
+                ssize_t n = TEMP_FAILURE_RETRY(read(s, pathbuf, pathlen - 1));
+                if (n <= 0) {
+                    result = -1;
+                } else {
+                    pathbuf[n] = '\0';
+                }
+            }
+        }
+    }
+    TEMP_FAILURE_RETRY(close(s));
+    return result;
+}
+
+int dump_backtrace_to_file(pid_t tid, int fd) {
+    int s = socket_local_client(DEBUGGER_SOCKET_NAME,
+            ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
+    if (s < 0) {
+        return -1;
+    }
+
+    debugger_msg_t msg;
+    memset(&msg, 0, sizeof(msg));
+    msg.tid = tid;
+    msg.action = DEBUGGER_ACTION_DUMP_BACKTRACE;
+
+    int result = 0;
+    if (TEMP_FAILURE_RETRY(write(s, &msg, sizeof(msg))) != sizeof(msg)) {
+        result = -1;
+    } else {
+        char ack;
+        if (TEMP_FAILURE_RETRY(read(s, &ack, 1)) != 1) {
+            result = -1;
+        } else {
+            char buffer[4096];
+            ssize_t n;
+            while ((n = TEMP_FAILURE_RETRY(read(s, buffer, sizeof(buffer)))) > 0) {
+                if (TEMP_FAILURE_RETRY(write(fd, buffer, n)) != n) {
+                    result = -1;
+                    break;
+                }
+            }
+        }
+    }
+    TEMP_FAILURE_RETRY(close(s));
+    return result;
+}
diff --git a/package/utils/adbd/src/libcutils/dir_hash.c b/package/utils/adbd/src/libcutils/dir_hash.c
new file mode 100644
index 0000000..098b5db
--- /dev/null
+++ b/package/utils/adbd/src/libcutils/dir_hash.c
@@ -0,0 +1,335 @@
+/*
+ * 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 <dirent.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sha1.h>
+#include <unistd.h>
+#include <limits.h>
+
+#include <sys/stat.h>
+
+#include <netinet/in.h>
+#include <resolv.h>
+
+#include <cutils/dir_hash.h>
+
+/**
+ * Copies, if it fits within max_output_string bytes, into output_string
+ * a hash of the contents, size, permissions, uid, and gid of the file
+ * specified by path, using the specified algorithm.  Returns the length
+ * of the output string, or a negative number if the buffer is too short.
+ */
+int get_file_hash(HashAlgorithm algorithm, const char *path,
+                  char *output_string, size_t max_output_string) {
+    SHA1_CTX context;
+    struct stat sb;
+    unsigned char md[SHA1_DIGEST_LENGTH];
+    int used;
+    size_t n;
+
+    if (algorithm != SHA_1) {
+        errno = EINVAL;
+        return -1;
+    }
+
+    if (stat(path, &sb) != 0) {
+        return -1;
+    }
+
+    if (S_ISLNK(sb.st_mode)) {
+        char buf[PATH_MAX];
+        int len;
+
+        len = readlink(path, buf, sizeof(buf));
+        if (len < 0) {
+            return -1;
+        }
+
+        SHA1Init(&context);
+        SHA1Update(&context, (unsigned char *) buf, len);
+        SHA1Final(md, &context);
+    } else if (S_ISREG(sb.st_mode)) {
+        char buf[10000];
+        FILE *f = fopen(path, "rb");
+        int len;
+
+        if (f == NULL) {
+            return -1;
+        }
+
+        SHA1Init(&context);
+
+        while ((len = fread(buf, 1, sizeof(buf), f)) > 0) {
+            SHA1Update(&context, (unsigned char *) buf, len);
+        }
+
+        if (ferror(f)) {
+            fclose(f);
+            return -1;
+        }
+
+        fclose(f);
+        SHA1Final(md, &context);
+    }
+
+    if (S_ISLNK(sb.st_mode) || S_ISREG(sb.st_mode)) {
+        used = b64_ntop(md, SHA1_DIGEST_LENGTH,
+                        output_string, max_output_string);
+        if (used < 0) {
+            errno = ENOSPC;
+            return -1;
+        }
+
+        n = snprintf(output_string + used, max_output_string - used,
+                     " %d 0%o %d %d", (int) sb.st_size, sb.st_mode,
+                     (int) sb.st_uid, (int) sb.st_gid);
+    } else {
+        n = snprintf(output_string, max_output_string,
+                     "- - 0%o %d %d", sb.st_mode,
+                     (int) sb.st_uid, (int) sb.st_gid);
+    }
+
+    if (n >= max_output_string - used) {
+        errno = ENOSPC;
+        return -(used + n);
+    }
+
+    return used + n;
+}
+
+struct list {
+    char *name;
+    struct list *next;
+};
+
+static int cmp(const void *a, const void *b) {
+    struct list *const *ra = a;
+    struct list *const *rb = b;
+
+    return strcmp((*ra)->name, (*rb)->name);
+}
+
+static int recurse(HashAlgorithm algorithm, const char *directory_path,
+                    struct list **out) {
+    struct list *list = NULL;
+    struct list *f;
+
+    struct dirent *de;
+    DIR *d = opendir(directory_path);
+
+    if (d == NULL) {
+        return -1;
+    }
+
+    while ((de = readdir(d)) != NULL) {
+        if (strcmp(de->d_name, ".") == 0) {
+            continue;
+        }
+        if (strcmp(de->d_name, "..") == 0) {
+            continue;
+        }
+
+        char *name = malloc(strlen(de->d_name) + 1);
+        struct list *node = malloc(sizeof(struct list));
+
+        if (name == NULL || node == NULL) {
+            struct list *next;
+            for (f = list; f != NULL; f = next) {
+                next = f->next;
+                free(f->name);
+                free(f);
+            }
+
+            free(name);
+            free(node);
+            closedir(d);
+            return -1;
+        }
+
+        strcpy(name, de->d_name);
+
+        node->name = name;
+        node->next = list;
+        list = node;
+    }
+
+    closedir(d);
+
+    for (f = list; f != NULL; f = f->next) {
+        struct stat sb;
+        char *name;
+        char outstr[NAME_MAX + 100];
+        char *keep;
+        struct list *res;
+
+        name = malloc(strlen(f->name) + strlen(directory_path) + 2);
+        if (name == NULL) {
+            struct list *next;
+            for (f = list; f != NULL; f = f->next) {
+                next = f->next;
+                free(f->name);
+                free(f);
+            }
+            for (f = *out; f != NULL; f = f->next) {
+                next = f->next;
+                free(f->name);
+                free(f);
+            }
+            *out = NULL;
+            return -1;
+        }
+
+        sprintf(name, "%s/%s", directory_path, f->name);
+
+        int len = get_file_hash(algorithm, name,
+                                outstr, sizeof(outstr));
+        if (len < 0) {
+            // should not happen
+            return -1;
+        }
+
+        keep = malloc(len + strlen(name) + 3);
+        res = malloc(sizeof(struct list));
+
+        if (keep == NULL || res == NULL) {
+            struct list *next;
+            for (f = list; f != NULL; f = f->next) {
+                next = f->next;
+                free(f->name);
+                free(f);
+            }
+            for (f = *out; f != NULL; f = f->next) {
+                next = f->next;
+                free(f->name);
+                free(f);
+            }
+            *out = NULL;
+
+            free(keep);
+            free(res);
+            return -1;
+        }
+
+        sprintf(keep, "%s %s\n", name, outstr);
+
+        res->name = keep;
+        res->next = *out;
+        *out = res;
+
+        if ((stat(name, &sb) == 0) && S_ISDIR(sb.st_mode)) {
+            if (recurse(algorithm, name, out) < 0) {
+                struct list *next;
+                for (f = list; f != NULL; f = next) {
+                    next = f->next;
+                    free(f->name);
+                    free(f);
+                }
+
+                return -1;
+            }
+        }
+    }
+
+    struct list *next;
+    for (f = list; f != NULL; f = next) {
+        next = f->next;
+
+        free(f->name);
+        free(f);
+    }
+}
+
+/**
+ * Allocates a string containing the names and hashes of all files recursively
+ * reached under the specified directory_path, using the specified algorithm.
+ * The string is returned as *output_string; the return value is the length
+ * of the string, or a negative number if there was a failure.
+ */
+int get_recursive_hash_manifest(HashAlgorithm algorithm,
+                                const char *directory_path,
+                                char **output_string) {
+    struct list *out = NULL;
+    struct list *r;
+    struct list **list;
+    int count = 0;
+    int len = 0;
+    int retlen = 0;
+    int i;
+    char *buf;
+    
+    if (recurse(algorithm, directory_path, &out) < 0) {
+        return -1;
+    }
+
+    for (r = out; r != NULL; r = r->next) {
+        count++;
+        len += strlen(r->name);
+    }
+
+    list = malloc(count * sizeof(struct list *));
+    if (list == NULL) {
+        struct list *next;
+        for (r = out; r != NULL; r = next) {
+            next = r->next;
+            free(r->name);
+            free(r);
+        }
+        return -1;
+    }
+
+    count = 0;
+    for (r = out; r != NULL; r = r->next) {
+        list[count++] = r;
+    }
+
+    qsort(list, count, sizeof(struct list *), cmp);
+
+    buf = malloc(len + 1);
+    if (buf == NULL) {
+        struct list *next;
+        for (r = out; r != NULL; r = next) {
+            next = r->next;
+            free(r->name);
+            free(r);
+        }
+        free(list);
+        return -1;
+    }
+
+    for (i = 0; i < count; i++) {
+        int n = strlen(list[i]->name);
+
+        strcpy(buf + retlen, list[i]->name);
+        retlen += n;
+    }
+
+    free(list);
+
+    struct list *next;
+    for (r = out; r != NULL; r = next) {
+        next = r->next;
+
+        free(r->name);
+        free(r);
+    }
+
+    *output_string = buf;
+    return retlen;
+}
diff --git a/package/utils/adbd/src/libcutils/dlmalloc_stubs.c b/package/utils/adbd/src/libcutils/dlmalloc_stubs.c
new file mode 100644
index 0000000..2db473d
--- /dev/null
+++ b/package/utils/adbd/src/libcutils/dlmalloc_stubs.c
@@ -0,0 +1,36 @@
+/*
+ * 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 "log/log.h"
+
+#define UNUSED __attribute__((__unused__))
+
+/*
+ * Stubs for functions defined in bionic/libc/bionic/dlmalloc.c. These
+ * are used in host builds, as the host libc will not contain these
+ * functions.
+ */
+void dlmalloc_inspect_all(void(*handler)(void*, void *, size_t, void*) UNUSED,
+                          void* arg UNUSED)
+{
+  ALOGW("Called host unimplemented stub: dlmalloc_inspect_all");
+}
+
+int dlmalloc_trim(size_t unused UNUSED)
+{
+  ALOGW("Called host unimplemented stub: dlmalloc_trim");
+  return 0;
+}
diff --git a/package/utils/adbd/src/libcutils/fs.c b/package/utils/adbd/src/libcutils/fs.c
new file mode 100644
index 0000000..45c7add
--- /dev/null
+++ b/package/utils/adbd/src/libcutils/fs.c
@@ -0,0 +1,237 @@
+/*
+ * Copyright (C) 2012 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 LOG_TAG "cutils"
+
+/* These defines are only needed because prebuilt headers are out of date */
+#define __USE_XOPEN2K8 1
+#define _ATFILE_SOURCE 1
+#define _GNU_SOURCE 1
+
+#include <cutils/fs.h>
+#include <cutils/log.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <dirent.h>
+
+#define ALL_PERMS (S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO)
+#define BUF_SIZE 64
+
+int fs_prepare_dir(const char* path, mode_t mode, uid_t uid, gid_t gid) {
+    // Check if path needs to be created
+    struct stat sb;
+    if (TEMP_FAILURE_RETRY(lstat(path, &sb)) == -1) {
+        if (errno == ENOENT) {
+            goto create;
+        } else {
+            ALOGE("Failed to lstat(%s): %s", path, strerror(errno));
+            return -1;
+        }
+    }
+
+    // Exists, verify status
+    if (!S_ISDIR(sb.st_mode)) {
+        ALOGE("Not a directory: %s", path);
+        return -1;
+    }
+    if (((sb.st_mode & ALL_PERMS) == mode) && (sb.st_uid == uid) && (sb.st_gid == gid)) {
+        return 0;
+    } else {
+        goto fixup;
+    }
+
+create:
+    if (TEMP_FAILURE_RETRY(mkdir(path, mode)) == -1) {
+        if (errno != EEXIST) {
+            ALOGE("Failed to mkdir(%s): %s", path, strerror(errno));
+            return -1;
+        }
+    }
+
+fixup:
+    if (TEMP_FAILURE_RETRY(chmod(path, mode)) == -1) {
+        ALOGE("Failed to chmod(%s, %d): %s", path, mode, strerror(errno));
+        return -1;
+    }
+    if (TEMP_FAILURE_RETRY(chown(path, uid, gid)) == -1) {
+        ALOGE("Failed to chown(%s, %d, %d): %s", path, uid, gid, strerror(errno));
+        return -1;
+    }
+
+    return 0;
+}
+
+int fs_read_atomic_int(const char* path, int* out_value) {
+    int fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY));
+    if (fd == -1) {
+        ALOGE("Failed to read %s: %s", path, strerror(errno));
+        return -1;
+    }
+
+    char buf[BUF_SIZE];
+    if (TEMP_FAILURE_RETRY(read(fd, buf, BUF_SIZE)) == -1) {
+        ALOGE("Failed to read %s: %s", path, strerror(errno));
+        goto fail;
+    }
+    if (sscanf(buf, "%d", out_value) != 1) {
+        ALOGE("Failed to parse %s: %s", path, strerror(errno));
+        goto fail;
+    }
+    close(fd);
+    return 0;
+
+fail:
+    close(fd);
+    *out_value = -1;
+    return -1;
+}
+
+int fs_write_atomic_int(const char* path, int value) {
+    char temp[PATH_MAX];
+    if (snprintf(temp, PATH_MAX, "%s.XXXXXX", path) >= PATH_MAX) {
+        ALOGE("Path too long");
+        return -1;
+    }
+
+    int fd = TEMP_FAILURE_RETRY(mkstemp(temp));
+    if (fd == -1) {
+        ALOGE("Failed to open %s: %s", temp, strerror(errno));
+        return -1;
+    }
+
+    char buf[BUF_SIZE];
+    int len = snprintf(buf, BUF_SIZE, "%d", value) + 1;
+    if (len > BUF_SIZE) {
+        ALOGE("Value %d too large: %s", value, strerror(errno));
+        goto fail;
+    }
+    if (TEMP_FAILURE_RETRY(write(fd, buf, len)) < len) {
+        ALOGE("Failed to write %s: %s", temp, strerror(errno));
+        goto fail;
+    }
+    if (close(fd) == -1) {
+        ALOGE("Failed to close %s: %s", temp, strerror(errno));
+        goto fail_closed;
+    }
+
+    if (rename(temp, path) == -1) {
+        ALOGE("Failed to rename %s to %s: %s", temp, path, strerror(errno));
+        goto fail_closed;
+    }
+
+    return 0;
+
+fail:
+    close(fd);
+fail_closed:
+    unlink(temp);
+    return -1;
+}
+
+#ifndef __APPLE__
+
+int fs_mkdirs(const char* path, mode_t mode) {
+    int res = 0;
+    int fd = 0;
+    struct stat sb;
+    char* buf = strdup(path);
+
+    if (*buf != '/') {
+        ALOGE("Relative paths are not allowed: %s", buf);
+        res = -EINVAL;
+        goto done;
+    }
+
+    if ((fd = open("/", 0)) == -1) {
+        ALOGE("Failed to open(/): %s", strerror(errno));
+        res = -errno;
+        goto done;
+    }
+
+    char* segment = buf + 1;
+    char* p = segment;
+    while (*p != '\0') {
+        if (*p == '/') {
+            *p = '\0';
+
+            if (!strcmp(segment, "..") || !strcmp(segment, ".") || !strcmp(segment, "")) {
+                ALOGE("Invalid path: %s", buf);
+                res = -EINVAL;
+                goto done_close;
+            }
+
+            if (fstatat(fd, segment, &sb, AT_SYMLINK_NOFOLLOW) != 0) {
+                if (errno == ENOENT) {
+                    /* Nothing there yet; let's create it! */
+                    if (mkdirat(fd, segment, mode) != 0) {
+                        if (errno == EEXIST) {
+                            /* We raced with someone; ignore */
+                        } else {
+                            ALOGE("Failed to mkdirat(%s): %s", buf, strerror(errno));
+                            res = -errno;
+                            goto done_close;
+                        }
+                    }
+                } else {
+                    ALOGE("Failed to fstatat(%s): %s", buf, strerror(errno));
+                    res = -errno;
+                    goto done_close;
+                }
+            } else {
+                if (S_ISLNK(sb.st_mode)) {
+                    ALOGE("Symbolic links are not allowed: %s", buf);
+                    res = -ELOOP;
+                    goto done_close;
+                }
+                if (!S_ISDIR(sb.st_mode)) {
+                    ALOGE("Existing segment not a directory: %s", buf);
+                    res = -ENOTDIR;
+                    goto done_close;
+                }
+            }
+
+            /* Yay, segment is ready for us to step into */
+            int next_fd;
+            if ((next_fd = openat(fd, segment, O_NOFOLLOW | O_CLOEXEC)) == -1) {
+                ALOGE("Failed to openat(%s): %s", buf, strerror(errno));
+                res = -errno;
+                goto done_close;
+            }
+
+            close(fd);
+            fd = next_fd;
+
+            *p = '/';
+            segment = p + 1;
+        }
+        p++;
+    }
+
+done_close:
+    close(fd);
+done:
+    free(buf);
+    return res;
+}
+
+#endif
diff --git a/package/utils/adbd/src/libcutils/hashmap.c b/package/utils/adbd/src/libcutils/hashmap.c
new file mode 100644
index 0000000..65539ea
--- /dev/null
+++ b/package/utils/adbd/src/libcutils/hashmap.c
@@ -0,0 +1,351 @@
+/*
+ * 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 <cutils/hashmap.h>
+#include <assert.h>
+#include <errno.h>
+#include <cutils/threads.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+#include <sys/types.h>
+
+typedef struct Entry Entry;
+struct Entry {
+    void* key;
+    int hash;
+    void* value;
+    Entry* next;
+};
+
+struct Hashmap {
+    Entry** buckets;
+    size_t bucketCount;
+    int (*hash)(void* key);
+    bool (*equals)(void* keyA, void* keyB);
+    mutex_t lock; 
+    size_t size;
+};
+
+Hashmap* hashmapCreate(size_t initialCapacity,
+        int (*hash)(void* key), bool (*equals)(void* keyA, void* keyB)) {
+    assert(hash != NULL);
+    assert(equals != NULL);
+    
+    Hashmap* map = malloc(sizeof(Hashmap));
+    if (map == NULL) {
+        return NULL;
+    }
+    
+    // 0.75 load factor.
+    size_t minimumBucketCount = initialCapacity * 4 / 3;
+    map->bucketCount = 1;
+    while (map->bucketCount <= minimumBucketCount) {
+        // Bucket count must be power of 2.
+        map->bucketCount <<= 1; 
+    }
+
+    map->buckets = calloc(map->bucketCount, sizeof(Entry*));
+    if (map->buckets == NULL) {
+        free(map);
+        return NULL;
+    }
+    
+    map->size = 0;
+
+    map->hash = hash;
+    map->equals = equals;
+    
+    mutex_init(&map->lock);
+    
+    return map;
+}
+
+/**
+ * Hashes the given key.
+ */
+static inline int hashKey(Hashmap* map, void* key) {
+    int h = map->hash(key);
+
+    // We apply this secondary hashing discovered by Doug Lea to defend
+    // against bad hashes.
+    h += ~(h << 9);
+    h ^= (((unsigned int) h) >> 14);
+    h += (h << 4);
+    h ^= (((unsigned int) h) >> 10);
+       
+    return h;
+}
+
+size_t hashmapSize(Hashmap* map) {
+    return map->size;
+}
+
+static inline size_t calculateIndex(size_t bucketCount, int hash) {
+    return ((size_t) hash) & (bucketCount - 1);
+}
+
+static void expandIfNecessary(Hashmap* map) {
+    // If the load factor exceeds 0.75...
+    if (map->size > (map->bucketCount * 3 / 4)) {
+        // Start off with a 0.33 load factor.
+        size_t newBucketCount = map->bucketCount << 1;
+        Entry** newBuckets = calloc(newBucketCount, sizeof(Entry*));
+        if (newBuckets == NULL) {
+            // Abort expansion.
+            return;
+        }
+        
+        // Move over existing entries.
+        size_t i;
+        for (i = 0; i < map->bucketCount; i++) {
+            Entry* entry = map->buckets[i];
+            while (entry != NULL) {
+                Entry* next = entry->next;
+                size_t index = calculateIndex(newBucketCount, entry->hash);
+                entry->next = newBuckets[index];
+                newBuckets[index] = entry;
+                entry = next;
+            }
+        }
+
+        // Copy over internals.
+        free(map->buckets);
+        map->buckets = newBuckets;
+        map->bucketCount = newBucketCount;
+    }
+}
+
+void hashmapLock(Hashmap* map) {
+    mutex_lock(&map->lock);
+}
+
+void hashmapUnlock(Hashmap* map) {
+    mutex_unlock(&map->lock);
+}
+
+void hashmapFree(Hashmap* map) {
+    size_t i;
+    for (i = 0; i < map->bucketCount; i++) {
+        Entry* entry = map->buckets[i];
+        while (entry != NULL) {
+            Entry* next = entry->next;
+            free(entry);
+            entry = next;
+        }
+    }
+    free(map->buckets);
+    mutex_destroy(&map->lock);
+    free(map);
+}
+
+int hashmapHash(void* key, size_t keySize) {
+    int h = keySize;
+    char* data = (char*) key;
+    size_t i;
+    for (i = 0; i < keySize; i++) {
+        h = h * 31 + *data;
+        data++;
+    }
+    return h;
+}
+
+static Entry* createEntry(void* key, int hash, void* value) {
+    Entry* entry = malloc(sizeof(Entry));
+    if (entry == NULL) {
+        return NULL;
+    }
+    entry->key = key;
+    entry->hash = hash;
+    entry->value = value;
+    entry->next = NULL;
+    return entry;
+}
+
+static inline bool equalKeys(void* keyA, int hashA, void* keyB, int hashB,
+        bool (*equals)(void*, void*)) {
+    if (keyA == keyB) {
+        return true;
+    }
+    if (hashA != hashB) {
+        return false;
+    }
+    return equals(keyA, keyB);
+}
+
+void* hashmapPut(Hashmap* map, void* key, void* value) {
+    int hash = hashKey(map, key);
+    size_t index = calculateIndex(map->bucketCount, hash);
+
+    Entry** p = &(map->buckets[index]);
+    while (true) {
+        Entry* current = *p;
+
+        // Add a new entry.
+        if (current == NULL) {
+            *p = createEntry(key, hash, value);
+            if (*p == NULL) {
+                errno = ENOMEM;
+                return NULL;
+            }
+            map->size++;
+            expandIfNecessary(map);
+            return NULL;
+        }
+
+        // Replace existing entry.
+        if (equalKeys(current->key, current->hash, key, hash, map->equals)) {
+            void* oldValue = current->value;
+            current->value = value;
+            return oldValue;
+        }
+
+        // Move to next entry.
+        p = &current->next;
+    }
+}
+
+void* hashmapGet(Hashmap* map, void* key) {
+    int hash = hashKey(map, key);
+    size_t index = calculateIndex(map->bucketCount, hash);
+
+    Entry* entry = map->buckets[index];
+    while (entry != NULL) {
+        if (equalKeys(entry->key, entry->hash, key, hash, map->equals)) {
+            return entry->value;
+        }
+        entry = entry->next;
+    }
+
+    return NULL;
+}
+
+bool hashmapContainsKey(Hashmap* map, void* key) {
+    int hash = hashKey(map, key);
+    size_t index = calculateIndex(map->bucketCount, hash);
+
+    Entry* entry = map->buckets[index];
+    while (entry != NULL) {
+        if (equalKeys(entry->key, entry->hash, key, hash, map->equals)) {
+            return true;
+        }
+        entry = entry->next;
+    }
+
+    return false;
+}
+
+void* hashmapMemoize(Hashmap* map, void* key, 
+        void* (*initialValue)(void* key, void* context), void* context) {
+    int hash = hashKey(map, key);
+    size_t index = calculateIndex(map->bucketCount, hash);
+
+    Entry** p = &(map->buckets[index]);
+    while (true) {
+        Entry* current = *p;
+
+        // Add a new entry.
+        if (current == NULL) {
+            *p = createEntry(key, hash, NULL);
+            if (*p == NULL) {
+                errno = ENOMEM;
+                return NULL;
+            }
+            void* value = initialValue(key, context);
+            (*p)->value = value;
+            map->size++;
+            expandIfNecessary(map);
+            return value;
+        }
+
+        // Return existing value.
+        if (equalKeys(current->key, current->hash, key, hash, map->equals)) {
+            return current->value;
+        }
+
+        // Move to next entry.
+        p = &current->next;
+    }
+}
+
+void* hashmapRemove(Hashmap* map, void* key) {
+    int hash = hashKey(map, key);
+    size_t index = calculateIndex(map->bucketCount, hash);
+
+    // Pointer to the current entry.
+    Entry** p = &(map->buckets[index]);
+    Entry* current;
+    while ((current = *p) != NULL) {
+        if (equalKeys(current->key, current->hash, key, hash, map->equals)) {
+            void* value = current->value;
+            *p = current->next;
+            free(current);
+            map->size--;
+            return value;
+        }
+
+        p = &current->next;
+    }
+
+    return NULL;
+}
+
+void hashmapForEach(Hashmap* map, 
+        bool (*callback)(void* key, void* value, void* context),
+        void* context) {
+    size_t i;
+    for (i = 0; i < map->bucketCount; i++) {
+        Entry* entry = map->buckets[i];
+        while (entry != NULL) {
+            Entry *next = entry->next;
+            if (!callback(entry->key, entry->value, context)) {
+                return;
+            }
+            entry = next;
+        }
+    }
+}
+
+size_t hashmapCurrentCapacity(Hashmap* map) {
+    size_t bucketCount = map->bucketCount;
+    return bucketCount * 3 / 4;
+}
+
+size_t hashmapCountCollisions(Hashmap* map) {
+    size_t collisions = 0;
+    size_t i;
+    for (i = 0; i < map->bucketCount; i++) {
+        Entry* entry = map->buckets[i];
+        while (entry != NULL) {
+            if (entry->next != NULL) {
+                collisions++;
+            }
+            entry = entry->next;
+        }
+    }
+    return collisions;
+}
+
+int hashmapIntHash(void* key) {
+    // Return the key value itself.
+    return *((int*) key);
+}
+
+bool hashmapIntEquals(void* keyA, void* keyB) {
+    int a = *((int*) keyA);
+    int b = *((int*) keyB);
+    return a == b;
+}
diff --git a/package/utils/adbd/src/libcutils/iosched_policy.c b/package/utils/adbd/src/libcutils/iosched_policy.c
new file mode 100644
index 0000000..a6da9ca
--- /dev/null
+++ b/package/utils/adbd/src/libcutils/iosched_policy.c
@@ -0,0 +1,58 @@
+/*
+** Copyright 2007-2014, 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/iosched_policy.h>
+
+#ifdef HAVE_ANDROID_OS
+#include <linux/ioprio.h>
+#include <sys/syscall.h>
+#define __android_unused
+#else
+#define __android_unused __attribute__((__unused__))
+#endif
+
+int android_set_ioprio(int pid __android_unused, IoSchedClass clazz __android_unused, int ioprio __android_unused) {
+#ifdef HAVE_ANDROID_OS
+    if (syscall(SYS_ioprio_set, IOPRIO_WHO_PROCESS, pid, ioprio | (clazz << IOPRIO_CLASS_SHIFT))) {
+        return -1;
+    }
+#endif
+    return 0;
+}
+
+int android_get_ioprio(int pid __android_unused, IoSchedClass *clazz, int *ioprio) {
+#ifdef HAVE_ANDROID_OS
+    int rc;
+
+    if ((rc = syscall(SYS_ioprio_get, IOPRIO_WHO_PROCESS, pid)) < 0) {
+        return -1;
+    }
+
+    *clazz = (rc >> IOPRIO_CLASS_SHIFT);
+    *ioprio = (rc & 0xff);
+#else
+    *clazz = IoSchedClass_NONE;
+    *ioprio = 0;
+#endif
+    return 0;
+}
diff --git a/package/utils/adbd/src/libcutils/klog.c b/package/utils/adbd/src/libcutils/klog.c
new file mode 100644
index 0000000..fbb7b72
--- /dev/null
+++ b/package/utils/adbd/src/libcutils/klog.c
@@ -0,0 +1,76 @@
+/*
+ * 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 <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <cutils/klog.h>
+
+static int klog_fd = -1;
+static int klog_level = KLOG_DEFAULT_LEVEL;
+
+int klog_get_level(void) {
+    return klog_level;
+}
+
+void klog_set_level(int level) {
+    klog_level = level;
+}
+
+void klog_init(void)
+{
+    static const char *name = "/dev/__kmsg__";
+
+    if (klog_fd >= 0) return; /* Already initialized */
+
+    if (mknod(name, S_IFCHR | 0600, (1 << 8) | 11) == 0) {
+        klog_fd = open(name, O_WRONLY);
+        if (klog_fd < 0)
+                return;
+        fcntl(klog_fd, F_SETFD, FD_CLOEXEC);
+        unlink(name);
+    }
+}
+
+#define LOG_BUF_MAX 512
+
+void klog_vwrite(int level, const char *fmt, va_list ap)
+{
+    char buf[LOG_BUF_MAX];
+
+    if (level > klog_level) return;
+    if (klog_fd < 0) klog_init();
+    if (klog_fd < 0) return;
+
+    vsnprintf(buf, LOG_BUF_MAX, fmt, ap);
+    buf[LOG_BUF_MAX - 1] = 0;
+
+    write(klog_fd, buf, strlen(buf));
+}
+
+void klog_write(int level, const char *fmt, ...)
+{
+    va_list ap;
+    va_start(ap, fmt);
+    klog_vwrite(level, fmt, ap);
+    va_end(ap);
+}
diff --git a/package/utils/adbd/src/libcutils/load_file.c b/package/utils/adbd/src/libcutils/load_file.c
new file mode 100644
index 0000000..99f2965
--- /dev/null
+++ b/package/utils/adbd/src/libcutils/load_file.c
@@ -0,0 +1,51 @@
+/* libs/cutils/load_file.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.
+*/
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+void *load_file(const char *fn, unsigned *_sz)
+{
+    char *data;
+    int sz;
+    int fd;
+
+    data = 0;
+    fd = open(fn, O_RDONLY);
+    if(fd < 0) return 0;
+
+    sz = lseek(fd, 0, SEEK_END);
+    if(sz < 0) goto oops;
+
+    if(lseek(fd, 0, SEEK_SET) != 0) goto oops;
+
+    data = (char*) malloc(sz + 1);
+    if(data == 0) goto oops;
+
+    if(read(fd, data, sz) != sz) goto oops;
+    close(fd);
+    data[sz] = 0;
+
+    if(_sz) *_sz = sz;
+    return data;
+
+oops:
+    close(fd);
+    if(data != 0) free(data);
+    return 0;
+}
diff --git a/package/utils/adbd/src/libcutils/loghack.h b/package/utils/adbd/src/libcutils/loghack.h
new file mode 100644
index 0000000..750cab0
--- /dev/null
+++ b/package/utils/adbd/src/libcutils/loghack.h
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+/**
+ * This is a temporary hack to enable logging from cutils.
+ */
+
+#ifndef _CUTILS_LOGHACK_H
+#define _CUTILS_LOGHACK_H
+
+#ifdef HAVE_ANDROID_OS
+#include <cutils/log.h>
+#else
+#include <stdio.h>
+#define ALOG(level, ...) \
+        ((void)printf("cutils:" level "/" LOG_TAG ": " __VA_ARGS__))
+#define ALOGV(...)   ALOG("V", __VA_ARGS__)
+#define ALOGD(...)   ALOG("D", __VA_ARGS__)
+#define ALOGI(...)   ALOG("I", __VA_ARGS__)
+#define ALOGW(...)   ALOG("W", __VA_ARGS__)
+#define ALOGE(...)   ALOG("E", __VA_ARGS__)
+#define LOG_ALWAYS_FATAL(...)   do { ALOGE(__VA_ARGS__); exit(1); } while (0)
+#endif
+
+#endif // _CUTILS_LOGHACK_H
diff --git a/package/utils/adbd/src/libcutils/memory.c b/package/utils/adbd/src/libcutils/memory.c
new file mode 100644
index 0000000..6486b45
--- /dev/null
+++ b/package/utils/adbd/src/libcutils/memory.c
@@ -0,0 +1,91 @@
+/*
+ * 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 <cutils/memory.h>
+
+#if !HAVE_MEMSET16
+void android_memset16(uint16_t* dst, uint16_t value, size_t size)
+{
+    size >>= 1;
+    while (size--) {
+        *dst++ = value;
+    }
+}
+#endif
+
+#if !HAVE_MEMSET32
+void android_memset32(uint32_t* dst, uint32_t value, size_t size)
+{
+    size >>= 2;
+    while (size--) {
+        *dst++ = value;
+    }
+}
+#endif
+
+#if !HAVE_STRLCPY
+/*
+ * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <string.h>
+
+/* Implementation of strlcpy() for platforms that don't already have it. */
+
+/*
+ * Copy src to string dst of size siz.  At most siz-1 characters
+ * will be copied.  Always NUL terminates (unless siz == 0).
+ * Returns strlen(src); if retval >= siz, truncation occurred.
+ */
+size_t
+strlcpy(char *dst, const char *src, size_t siz)
+{
+	char *d = dst;
+	const char *s = src;
+	size_t n = siz;
+
+	/* Copy as many bytes as will fit */
+	if (n != 0) {
+		while (--n != 0) {
+			if ((*d++ = *s++) == '\0')
+				break;
+		}
+  }
+
+	/* Not enough room in dst, add NUL and traverse rest of src */
+	if (n == 0) {
+		if (siz != 0)
+			*d = '\0';		/* NUL-terminate dst */
+		while (*s++)
+			;
+	}
+
+	return(s - src - 1);	/* count does not include NUL */
+}
+#endif
diff --git a/package/utils/adbd/src/libcutils/multiuser.c b/package/utils/adbd/src/libcutils/multiuser.c
new file mode 100644
index 0000000..7c74bb8
--- /dev/null
+++ b/package/utils/adbd/src/libcutils/multiuser.c
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2012 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 <cutils/multiuser.h>
+
+userid_t multiuser_get_user_id(uid_t uid) {
+    return uid / MULTIUSER_APP_PER_USER_RANGE;
+}
+
+appid_t multiuser_get_app_id(uid_t uid) {
+    return uid % MULTIUSER_APP_PER_USER_RANGE;
+}
+
+uid_t multiuser_get_uid(userid_t userId, appid_t appId) {
+    return userId * MULTIUSER_APP_PER_USER_RANGE + (appId % MULTIUSER_APP_PER_USER_RANGE);
+}
diff --git a/package/utils/adbd/src/libcutils/native_handle.c b/package/utils/adbd/src/libcutils/native_handle.c
new file mode 100644
index 0000000..4089968
--- /dev/null
+++ b/package/utils/adbd/src/libcutils/native_handle.c
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "NativeHandle"
+
+#include <stdint.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <cutils/log.h>
+#include <cutils/native_handle.h>
+
+native_handle_t* native_handle_create(int numFds, int numInts)
+{
+    native_handle_t* h = malloc(
+            sizeof(native_handle_t) + sizeof(int)*(numFds+numInts));
+
+    h->version = sizeof(native_handle_t);
+    h->numFds = numFds;
+    h->numInts = numInts;
+    return h;
+}
+
+int native_handle_delete(native_handle_t* h)
+{
+    if (h) {
+        if (h->version != sizeof(native_handle_t))
+            return -EINVAL;
+        free(h);
+    }
+    return 0;
+}
+
+int native_handle_close(const native_handle_t* h)
+{
+    if (h->version != sizeof(native_handle_t))
+        return -EINVAL;
+
+    const int numFds = h->numFds;
+    int i;
+    for (i=0 ; i<numFds ; i++) {
+        close(h->data[i]);
+    }
+    return 0;
+}
diff --git a/package/utils/adbd/src/libcutils/open_memstream.c b/package/utils/adbd/src/libcutils/open_memstream.c
new file mode 100644
index 0000000..5b4388a
--- /dev/null
+++ b/package/utils/adbd/src/libcutils/open_memstream.c
@@ -0,0 +1,381 @@
+/*
+ * Copyright (C) 2010 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 HAVE_OPEN_MEMSTREAM
+
+/*
+ * Implementation of the POSIX open_memstream() function, which Linux has
+ * but BSD lacks.
+ *
+ * Summary:
+ * - Works like a file-backed FILE* opened with fopen(name, "w"), but the
+ *   backing is a chunk of memory rather than a file.
+ * - The buffer expands as you write more data.  Seeking past the end
+ *   of the file and then writing to it zero-fills the gap.
+ * - The values at "*bufp" and "*sizep" should be considered read-only,
+ *   and are only valid immediately after an fflush() or fclose().
+ * - A '\0' is maintained just past the end of the file. This is not included
+ *   in "*sizep".  (The behavior w.r.t. fseek() is not clearly defined.
+ *   The spec says the null byte is written when a write() advances EOF,
+ *   but it looks like glibc ensures the null byte is always found at EOF,
+ *   even if you just seeked backwards.  The example on the opengroup.org
+ *   page suggests that this is the expected behavior.  The null must be
+ *   present after a no-op fflush(), which we can't see, so we have to save
+ *   and restore it.  Annoying, but allows file truncation.)
+ * - After fclose(), the caller must eventually free(*bufp).
+ *
+ * This is built out of funopen(), which BSD has but Linux lacks.  There is
+ * no flush() operator, so we need to keep the user pointers up to date
+ * after each operation.
+ *
+ * I don't think Windows has any of the above, but we don't need to use
+ * them there, so we just supply a stub.
+ */
+#include <cutils/open_memstream.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+
+#if 0
+# define DBUG(x) printf x
+#else
+# define DBUG(x) ((void)0)
+#endif
+
+#ifdef HAVE_FUNOPEN
+
+/*
+ * Definition of a seekable, write-only memory stream.
+ */
+typedef struct {
+    char**      bufp;       /* pointer to buffer pointer */
+    size_t*     sizep;      /* pointer to eof */
+
+    size_t      allocSize;  /* size of buffer */
+    size_t      eof;        /* furthest point we've written to */
+    size_t      offset;     /* current write offset */
+    char        saved;      /* required by NUL handling */
+} MemStream;
+
+#define kInitialSize    1024
+
+/*
+ * Ensure that we have enough storage to write "size" bytes at the
+ * current offset.  We also have to take into account the extra '\0'
+ * that we maintain just past EOF.
+ *
+ * Returns 0 on success.
+ */
+static int ensureCapacity(MemStream* stream, int writeSize)
+{
+    DBUG(("+++ ensureCap off=%d size=%d\n", stream->offset, writeSize));
+
+    size_t neededSize = stream->offset + writeSize + 1;
+    if (neededSize <= stream->allocSize)
+        return 0;
+
+    size_t newSize;
+
+    if (stream->allocSize == 0) {
+        newSize = kInitialSize;
+    } else {
+        newSize = stream->allocSize;
+        newSize += newSize / 2;             /* expand by 3/2 */
+    }
+
+    if (newSize < neededSize)
+        newSize = neededSize;
+    DBUG(("+++ realloc %p->%p to size=%d\n",
+        stream->bufp, *stream->bufp, newSize));
+    char* newBuf = (char*) realloc(*stream->bufp, newSize);
+    if (newBuf == NULL)
+        return -1;
+
+    *stream->bufp = newBuf;
+    stream->allocSize = newSize;
+    return 0;
+}
+
+/*
+ * Write data to a memstream, expanding the buffer if necessary.
+ *
+ * If we previously seeked beyond EOF, zero-fill the gap.
+ *
+ * Returns the number of bytes written.
+ */
+static int write_memstream(void* cookie, const char* buf, int size)
+{
+    MemStream* stream = (MemStream*) cookie;
+
+    if (ensureCapacity(stream, size) < 0)
+        return -1;
+
+    /* seeked past EOF earlier? */
+    if (stream->eof < stream->offset) {
+        DBUG(("+++ zero-fill gap from %d to %d\n",
+            stream->eof, stream->offset-1));
+        memset(*stream->bufp + stream->eof, '\0',
+            stream->offset - stream->eof);
+    }
+
+    /* copy data, advance write pointer */
+    memcpy(*stream->bufp + stream->offset, buf, size);
+    stream->offset += size;
+
+    if (stream->offset > stream->eof) {
+        /* EOF has advanced, update it and append null byte */
+        DBUG(("+++ EOF advanced to %d, appending nul\n", stream->offset));
+        assert(stream->offset < stream->allocSize);
+        stream->eof = stream->offset;
+    } else {
+        /* within previously-written area; save char we're about to stomp */
+        DBUG(("+++ within written area, saving '%c' at %d\n",
+            *(*stream->bufp + stream->offset), stream->offset));
+        stream->saved = *(*stream->bufp + stream->offset);
+    }
+    *(*stream->bufp + stream->offset) = '\0';
+    *stream->sizep = stream->offset;
+
+    return size;
+}
+
+/*
+ * Seek within a memstream.
+ *
+ * Returns the new offset, or -1 on failure.
+ */
+static fpos_t seek_memstream(void* cookie, fpos_t offset, int whence)
+{
+    MemStream* stream = (MemStream*) cookie;
+    off_t newPosn = (off_t) offset;
+
+    if (whence == SEEK_CUR) {
+        newPosn += stream->offset;
+    } else if (whence == SEEK_END) {
+        newPosn += stream->eof;
+    }
+
+    if (newPosn < 0 || ((fpos_t)((size_t) newPosn)) != newPosn) {
+        /* bad offset - negative or huge */
+        DBUG(("+++ bogus seek offset %ld\n", (long) newPosn));
+        errno = EINVAL;
+        return (fpos_t) -1;
+    }
+
+    if (stream->offset < stream->eof) {
+        /*
+         * We were pointing to an area we'd already written to, which means
+         * we stomped on a character and must now restore it.
+         */
+        DBUG(("+++ restoring char '%c' at %d\n",
+            stream->saved, stream->offset));
+        *(*stream->bufp + stream->offset) = stream->saved;
+    }
+
+    stream->offset = (size_t) newPosn;
+
+    if (stream->offset < stream->eof) {
+        /*
+         * We're seeked backward into the stream.  Preserve the character
+         * at EOF and stomp it with a NUL.
+         */
+        stream->saved = *(*stream->bufp + stream->offset);
+        *(*stream->bufp + stream->offset) = '\0';
+        *stream->sizep = stream->offset;
+    } else {
+        /*
+         * We're positioned at, or possibly beyond, the EOF.  We want to
+         * publish the current EOF, not the current position.
+         */
+        *stream->sizep = stream->eof;
+    }
+
+    return newPosn;
+}
+
+/*
+ * Close the memstream.  We free everything but the data buffer.
+ */
+static int close_memstream(void* cookie)
+{
+    free(cookie);
+    return 0;
+}
+
+/*
+ * Prepare a memstream.
+ */
+FILE* open_memstream(char** bufp, size_t* sizep)
+{
+    FILE* fp;
+    MemStream* stream;
+
+    if (bufp == NULL || sizep == NULL) {
+        errno = EINVAL;
+        return NULL;
+    }
+
+    stream = (MemStream*) calloc(1, sizeof(MemStream));
+    if (stream == NULL)
+        return NULL;
+
+    fp = funopen(stream,
+        NULL, write_memstream, seek_memstream, close_memstream);
+    if (fp == NULL) {
+        free(stream);
+        return NULL;
+    }
+
+    *sizep = 0;
+    *bufp = NULL;
+    stream->bufp = bufp;
+    stream->sizep = sizep;
+
+    return fp;
+}
+
+#else /*not HAVE_FUNOPEN*/
+FILE* open_memstream(char** bufp, size_t* sizep)
+{
+    abort();
+}
+#endif /*HAVE_FUNOPEN*/
+
+
+
+#if 0
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/*
+ * Simple regression test.
+ *
+ * To test on desktop Linux with valgrind, it's possible to make a simple
+ * change to open_memstream() to use fopencookie instead:
+ *
+ *  cookie_io_functions_t iofuncs =
+ *      { NULL, write_memstream, seek_memstream, close_memstream };
+ *  fp = fopencookie(stream, "w", iofuncs);
+ *
+ * (Some tweaks to seek_memstream are also required, as that takes a
+ * pointer to an offset rather than an offset, and returns 0 or -1.)
+ */
+int testMemStream(void)
+{
+    FILE *stream;
+    char *buf;
+    size_t len;
+    off_t eob;
+
+    printf("Test1\n");
+
+    /* std example */
+    stream = open_memstream(&buf, &len);
+    fprintf(stream, "hello my world");
+    fflush(stream);
+    printf("buf=%s, len=%zu\n", buf, len);
+    eob = ftello(stream);
+    fseeko(stream, 0, SEEK_SET);
+    fprintf(stream, "good-bye");
+    fseeko(stream, eob, SEEK_SET);
+    fclose(stream);
+    printf("buf=%s, len=%zu\n", buf, len);
+    free(buf);
+
+    printf("Test2\n");
+
+    /* std example without final seek-to-end */
+    stream = open_memstream(&buf, &len);
+    fprintf(stream, "hello my world");
+    fflush(stream);
+    printf("buf=%s, len=%zu\n", buf, len);
+    eob = ftello(stream);
+    fseeko(stream, 0, SEEK_SET);
+    fprintf(stream, "good-bye");
+    //fseeko(stream, eob, SEEK_SET);
+    fclose(stream);
+    printf("buf=%s, len=%zu\n", buf, len);
+    free(buf);
+
+    printf("Test3\n");
+
+    /* fancy example; should expand buffer with writes */
+    static const int kCmpLen = 1024 + 128;
+    char* cmp = malloc(kCmpLen);
+    memset(cmp, 0, 1024);
+    memset(cmp+1024, 0xff, kCmpLen-1024);
+    sprintf(cmp, "This-is-a-tes1234");
+    sprintf(cmp + 1022, "abcdef");
+
+    stream = open_memstream (&buf, &len);
+    setvbuf(stream, NULL, _IONBF, 0);   /* note: crashes in glibc with this */
+    fprintf(stream, "This-is-a-test");
+    fseek(stream, -1, SEEK_CUR);    /* broken in glibc; can use {13,SEEK_SET} */
+    fprintf(stream, "1234");
+    fseek(stream, 1022, SEEK_SET);
+    fputc('a', stream);
+    fputc('b', stream);
+    fputc('c', stream);
+    fputc('d', stream);
+    fputc('e', stream);
+    fputc('f', stream);
+    fflush(stream);
+
+    if (memcmp(buf, cmp, len+1) != 0) {
+        printf("mismatch\n");
+    } else {
+        printf("match\n");
+    }
+
+    printf("Test4\n");
+    stream = open_memstream (&buf, &len);
+    fseek(stream, 5000, SEEK_SET);
+    fseek(stream, 4096, SEEK_SET);
+    fseek(stream, -1, SEEK_SET);        /* should have no effect */
+    fputc('x', stream);
+    if (ftell(stream) == 4097)
+        printf("good\n");
+    else
+        printf("BAD: offset is %ld\n", ftell(stream));
+
+    printf("DONE\n");
+
+    return 0;
+}
+
+/* expected output:
+Test1
+buf=hello my world, len=14
+buf=good-bye world, len=14
+Test2
+buf=hello my world, len=14
+buf=good-bye, len=8
+Test3
+match
+Test4
+good
+DONE
+*/
+
+#endif
+
+#endif /*!HAVE_OPEN_MEMSTREAM*/
diff --git a/package/utils/adbd/src/libcutils/partition_utils.c b/package/utils/adbd/src/libcutils/partition_utils.c
new file mode 100644
index 0000000..823b162
--- /dev/null
+++ b/package/utils/adbd/src/libcutils/partition_utils.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2011, 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 <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/mount.h> /* for BLKGETSIZE */
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <cutils/properties.h>
+
+static int only_one_char(char *buf, int len, char c)
+{
+    int i, ret;
+
+    ret = 1;
+    for (i=0; i<len; i++) {
+        if (buf[i] != c) {
+            ret = 0;
+            break;
+        }
+    }
+    return ret;
+}
+
+int partition_wiped(char *source)
+{
+    char buf[4096];
+    int fd, ret;
+
+    if ((fd = open(source, O_RDONLY)) < 0) {
+        return 0;
+    }
+
+    ret = read(fd, buf, sizeof(buf));
+    close(fd);
+
+    if (ret != sizeof(buf)) {
+        return 0;
+    }
+
+    /* Check for all zeros */
+    if (only_one_char(buf, sizeof(buf), 0)) {
+       return 1;
+    }
+
+    /* Check for all ones */
+    if (only_one_char(buf, sizeof(buf), 0xff)) {
+       return 1;
+    }
+
+    return 0;
+}
+
diff --git a/package/utils/adbd/src/libcutils/process_name.c b/package/utils/adbd/src/libcutils/process_name.c
new file mode 100644
index 0000000..9c3dfb8
--- /dev/null
+++ b/package/utils/adbd/src/libcutils/process_name.c
@@ -0,0 +1,97 @@
+/*
+ * 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 <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#if defined(HAVE_PRCTL)
+#include <sys/prctl.h>
+#endif
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <cutils/process_name.h>
+#ifdef HAVE_ANDROID_OS
+#include <cutils/properties.h>
+#endif
+
+#define PROCESS_NAME_DEVICE "/sys/qemu_trace/process_name"
+
+static const char* process_name = "unknown";
+#ifdef HAVE_ANDROID_OS
+static int running_in_emulator = -1;
+#endif
+
+void set_process_name(const char* new_name) {
+#ifdef HAVE_ANDROID_OS
+    char  propBuf[PROPERTY_VALUE_MAX];
+#endif
+
+    if (new_name == NULL) {
+        return;
+    }
+
+    // We never free the old name. Someone else could be using it.
+    int len = strlen(new_name);
+    char* copy = (char*) malloc(len + 1);
+    strcpy(copy, new_name);
+    process_name = (const char*) copy;
+
+#if defined(HAVE_PRCTL)
+    if (len < 16) {
+        prctl(PR_SET_NAME, (unsigned long) new_name, 0, 0, 0);
+    } else {
+        prctl(PR_SET_NAME, (unsigned long) new_name + len - 15, 0, 0, 0);
+    }
+#endif
+
+#ifdef HAVE_ANDROID_OS
+    // If we know we are not running in the emulator, then return.
+    if (running_in_emulator == 0) {
+        return;
+    }
+
+    // If the "running_in_emulator" variable has not been initialized,
+    // then do it now.
+    if (running_in_emulator == -1) {
+        property_get("ro.kernel.qemu", propBuf, "");
+        if (propBuf[0] == '1') {
+            running_in_emulator = 1;
+        } else {
+            running_in_emulator = 0;
+            return;
+        }
+    }
+
+    // If the emulator was started with the "-trace file" command line option
+    // then we want to record the process name in the trace even if we are
+    // not currently tracing instructions (so that we will know the process
+    // name when we do start tracing instructions).  We do not need to execute
+    // this code if we are just running in the emulator without the "-trace"
+    // command line option, but we don't know that here and this function
+    // isn't called frequently enough to bother optimizing that case.
+    int fd = open(PROCESS_NAME_DEVICE, O_RDWR);
+    if (fd < 0)
+        return;
+    write(fd, process_name, strlen(process_name) + 1);
+    close(fd);
+#endif
+}
+
+const char* get_process_name(void) {
+    return process_name;
+}
diff --git a/package/utils/adbd/src/libcutils/properties.c b/package/utils/adbd/src/libcutils/properties.c
new file mode 100644
index 0000000..864e2e4
--- /dev/null
+++ b/package/utils/adbd/src/libcutils/properties.c
@@ -0,0 +1,424 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "properties"
+// #define LOG_NDEBUG 0
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <cutils/sockets.h>
+#include <errno.h>
+#include <assert.h>
+
+#include <inttypes.h>
+#include <cutils/properties.h>
+#include <stdbool.h>
+#include <inttypes.h>
+#include "loghack.h"
+
+int8_t property_get_bool(const char *key, int8_t default_value) {
+    if (!key) {
+        return default_value;
+    }
+
+    int8_t result = default_value;
+    char buf[PROPERTY_VALUE_MAX] = {'\0',};
+
+    int len = property_get(key, buf, "");
+    if (len == 1) {
+        char ch = buf[0];
+        if (ch == '0' || ch == 'n') {
+            result = false;
+        } else if (ch == '1' || ch == 'y') {
+            result = true;
+        }
+    } else if (len > 1) {
+         if (!strcmp(buf, "no") || !strcmp(buf, "false") || !strcmp(buf, "off")) {
+            result = false;
+        } else if (!strcmp(buf, "yes") || !strcmp(buf, "true") || !strcmp(buf, "on")) {
+            result = true;
+        }
+    }
+
+    return result;
+}
+
+// Convert string property to int (default if fails); return default value if out of bounds
+static intmax_t property_get_imax(const char *key, intmax_t lower_bound, intmax_t upper_bound,
+        intmax_t default_value) {
+    if (!key) {
+        return default_value;
+    }
+
+    intmax_t result = default_value;
+    char buf[PROPERTY_VALUE_MAX] = {'\0',};
+    char *end = NULL;
+
+    int len = property_get(key, buf, "");
+    if (len > 0) {
+        int tmp = errno;
+        errno = 0;
+
+        // Infer base automatically
+        result = strtoimax(buf, &end, /*base*/0);
+        if ((result == INTMAX_MIN || result == INTMAX_MAX) && errno == ERANGE) {
+            // Over or underflow
+            result = default_value;
+            ALOGV("%s(%s,%" PRIdMAX ") - overflow", __FUNCTION__, key, default_value);
+        } else if (result < lower_bound || result > upper_bound) {
+            // Out of range of requested bounds
+            result = default_value;
+            ALOGV("%s(%s,%" PRIdMAX ") - out of range", __FUNCTION__, key, default_value);
+        } else if (end == buf) {
+            // Numeric conversion failed
+            result = default_value;
+            ALOGV("%s(%s,%" PRIdMAX ") - numeric conversion failed",
+                    __FUNCTION__, key, default_value);
+        }
+
+        errno = tmp;
+    }
+
+    return result;
+}
+
+int64_t property_get_int64(const char *key, int64_t default_value) {
+    return (int64_t)property_get_imax(key, INT64_MIN, INT64_MAX, default_value);
+}
+
+int32_t property_get_int32(const char *key, int32_t default_value) {
+    return (int32_t)property_get_imax(key, INT32_MIN, INT32_MAX, default_value);
+}
+
+#ifdef HAVE_LIBC_SYSTEM_PROPERTIES
+
+#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
+#include <sys/_system_properties.h>
+
+int property_set(const char *key, const char *value)
+{
+    return __system_property_set(key, value);
+}
+
+int property_get(const char *key, char *value, const char *default_value)
+{
+    int len;
+
+    len = __system_property_get(key, value);
+    if(len > 0) {
+        return len;
+    }
+    if(default_value) {
+        len = strlen(default_value);
+        if (len >= PROPERTY_VALUE_MAX) {
+            len = PROPERTY_VALUE_MAX - 1;
+        }
+        memcpy(value, default_value, len);
+        value[len] = '\0';
+    }
+    return len;
+}
+
+struct property_list_callback_data
+{
+    void (*propfn)(const char *key, const char *value, void *cookie);
+    void *cookie;
+};
+
+static void property_list_callback(const prop_info *pi, void *cookie)
+{
+    char name[PROP_NAME_MAX];
+    char value[PROP_VALUE_MAX];
+    struct property_list_callback_data *data = cookie;
+
+    __system_property_read(pi, name, value);
+    data->propfn(name, value, data->cookie);
+}
+
+int property_list(
+        void (*propfn)(const char *key, const char *value, void *cookie),
+        void *cookie)
+{
+    struct property_list_callback_data data = { propfn, cookie };
+    return __system_property_foreach(property_list_callback, &data);
+}
+
+#elif defined(HAVE_SYSTEM_PROPERTY_SERVER)
+
+/*
+ * The Linux simulator provides a "system property server" that uses IPC
+ * to set/get/list properties.  The file descriptor is shared by all
+ * threads in the process, so we use a mutex to ensure that requests
+ * from multiple threads don't get interleaved.
+ */
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <pthread.h>
+
+static pthread_once_t gInitOnce = PTHREAD_ONCE_INIT;
+static pthread_mutex_t gPropertyFdLock = PTHREAD_MUTEX_INITIALIZER;
+static int gPropFd = -1;
+
+/*
+ * Connect to the properties server.
+ *
+ * Returns the socket descriptor on success.
+ */
+static int connectToServer(const char* fileName)
+{
+    int sock = -1;
+    int cc;
+
+    struct sockaddr_un addr;
+    
+    sock = socket(AF_UNIX, SOCK_STREAM, 0);
+    if (sock < 0) {
+        ALOGW("UNIX domain socket create failed (errno=%d)\n", errno);
+        return -1;
+    }
+
+    /* connect to socket; fails if file doesn't exist */
+    strcpy(addr.sun_path, fileName);    // max 108 bytes
+    addr.sun_family = AF_UNIX;
+    cc = connect(sock, (struct sockaddr*) &addr, SUN_LEN(&addr));
+    if (cc < 0) {
+        // ENOENT means socket file doesn't exist
+        // ECONNREFUSED means socket exists but nobody is listening
+        //ALOGW("AF_UNIX connect failed for '%s': %s\n",
+        //    fileName, strerror(errno));
+        close(sock);
+        return -1;
+    }
+
+    return sock;
+}
+
+/*
+ * Perform one-time initialization.
+ */
+static void init(void)
+{
+    assert(gPropFd == -1);
+
+    gPropFd = connectToServer(SYSTEM_PROPERTY_PIPE_NAME);
+    if (gPropFd < 0) {
+        //ALOGW("not connected to system property server\n");
+    } else {
+        //ALOGV("Connected to system property server\n");
+    }
+}
+
+int property_get(const char *key, char *value, const char *default_value)
+{
+    //char sendBuf[1+PROPERTY_KEY_MAX];
+    //char recvBuf[1+PROPERTY_VALUE_MAX];
+    //int len = -1;
+//
+    ////ALOGV("PROPERTY GET [%s]\n", key);
+//
+    //pthread_once(&gInitOnce, init);
+    //if (gPropFd < 0) {
+    //    /* this mimics the behavior of the device implementation */
+    //    if (default_value != NULL) {
+    //        strcpy(value, default_value);
+    //        len = strlen(value);
+    //    }
+    //    return len;
+    //}
+//
+    //if (strlen(key) >= PROPERTY_KEY_MAX) return -1;
+//
+    //memset(sendBuf, 0xdd, sizeof(sendBuf));    // placate valgrind
+//
+    //sendBuf[0] = (char) kSystemPropertyGet;
+    //strcpy(sendBuf+1, key);
+//
+    //pthread_mutex_lock(&gPropertyFdLock);
+    //if (write(gPropFd, sendBuf, sizeof(sendBuf)) != sizeof(sendBuf)) {
+    //    pthread_mutex_unlock(&gPropertyFdLock);
+    //    return -1;
+    //}
+    //if (read(gPropFd, recvBuf, sizeof(recvBuf)) != sizeof(recvBuf)) {
+    //    pthread_mutex_unlock(&gPropertyFdLock);
+    //    return -1;
+    //}
+    //pthread_mutex_unlock(&gPropertyFdLock);
+//
+    ///* first byte is 0 if value not defined, 1 if found */
+    //if (recvBuf[0] == 0) {
+    //    if (default_value != NULL) {
+    //        strcpy(value, default_value);
+    //        len = strlen(value);
+    //    } else {
+    //        /*
+    //         * If the value isn't defined, hand back an empty string and
+    //         * a zero length, rather than a failure.  This seems wrong,
+    //         * since you can't tell the difference between "undefined" and
+    //         * "defined but empty", but it's what the device does.
+    //         */
+    //        value[0] = '\0';
+    //        len = 0;
+    //    }
+    //} else if (recvBuf[0] == 1) {
+    //    strcpy(value, recvBuf+1);
+    //    len = strlen(value);
+    //} else {
+    //    ALOGE("Got strange response to property_get request (%d)\n",
+    //        recvBuf[0]);
+    //    assert(0);
+    //    return -1;
+    //}
+    ////ALOGV("PROP [found=%d def='%s'] (%d) [%s]: [%s]\n",
+    ////    recvBuf[0], default_value, len, key, value);
+//
+    //return len;
+    return 0;
+}
+
+
+int property_set(const char *key, const char *value)
+{
+    //char sendBuf[1+PROPERTY_KEY_MAX+PROPERTY_VALUE_MAX];
+    //char recvBuf[1];
+    //int result = -1;
+//
+    ////ALOGV("PROPERTY SET [%s]: [%s]\n", key, value);
+//
+    //pthread_once(&gInitOnce, init);
+    //if (gPropFd < 0)
+    //    return -1;
+//
+    //if (strlen(key) >= PROPERTY_KEY_MAX) return -1;
+    //if (strlen(value) >= PROPERTY_VALUE_MAX) return -1;
+//
+    //memset(sendBuf, 0xdd, sizeof(sendBuf));    // placate valgrind
+//
+    //sendBuf[0] = (char) kSystemPropertySet;
+    //strcpy(sendBuf+1, key);
+    //strcpy(sendBuf+1+PROPERTY_KEY_MAX, value);
+//
+    //pthread_mutex_lock(&gPropertyFdLock);
+    //if (write(gPropFd, sendBuf, sizeof(sendBuf)) != sizeof(sendBuf)) {
+    //    pthread_mutex_unlock(&gPropertyFdLock);
+    //    return -1;
+    //}
+    //if (read(gPropFd, recvBuf, sizeof(recvBuf)) != sizeof(recvBuf)) {
+    //    pthread_mutex_unlock(&gPropertyFdLock);
+    //    return -1;
+    //}
+    //pthread_mutex_unlock(&gPropertyFdLock);
+//
+    //if (recvBuf[0] != 1)
+    //    return -1;
+    return 0;
+}
+
+int property_list(void (*propfn)(const char *key, const char *value, void *cookie), 
+                  void *cookie)
+{
+    //ALOGV("PROPERTY LIST\n");
+    //pthread_once(&gInitOnce, init);
+    //if (gPropFd < 0)
+    //    return -1;
+
+    return 0;
+}
+
+#else
+
+/* SUPER-cheesy place-holder implementation for Win32 */
+
+//#include <cutils/threads.h>
+
+//static mutex_t  env_lock = MUTEX_INITIALIZER;
+
+int property_get(const char *key, char *value, const char *default_value)
+{
+    //char ename[PROPERTY_KEY_MAX + 6];
+    //char *p;
+    //int len;
+    //
+    //len = strlen(key);
+    //if(len >= PROPERTY_KEY_MAX) return -1;
+    //memcpy(ename, "PROP_", 5);
+    //memcpy(ename + 5, key, len + 1);
+    //
+    //mutex_lock(&env_lock);
+//
+    //p = getenv(ename);
+    //if(p == 0) p = "";
+    //len = strlen(p);
+    //if(len >= PROPERTY_VALUE_MAX) {
+    //    len = PROPERTY_VALUE_MAX - 1;
+    //}
+    //
+    //if((len == 0) && default_value) {
+    //    len = strlen(default_value);
+    //    memcpy(value, default_value, len + 1);
+    //} else {
+    //    memcpy(value, p, len);
+    //    value[len] = 0;
+    //}
+//
+    //mutex_unlock(&env_lock);
+    
+    //return len;
+    return 0;
+}
+
+
+int property_set(const char *key, const char *value)
+{
+//    char ename[PROPERTY_KEY_MAX + 6];
+//    char *p;
+//    int len;
+//    int r;
+//
+//    if(strlen(value) >= PROPERTY_VALUE_MAX) return -1;
+//    
+//    len = strlen(key);
+//    if(len >= PROPERTY_KEY_MAX) return -1;
+//    memcpy(ename, "PROP_", 5);
+//    memcpy(ename + 5, key, len + 1);
+//
+//    mutex_lock(&env_lock);
+//#ifdef HAVE_MS_C_RUNTIME
+//    {
+//        char  temp[256];
+//        snprintf( temp, sizeof(temp), "%s=%s", ename, value);
+//        putenv(temp);
+//        r = 0;
+//    }
+//#else    
+//    r = setenv(ename, value, 1);
+//#endif    
+//    mutex_unlock(&env_lock);
+//    
+//    return r;
+    return 0;
+}
+
+int property_list(void (*propfn)(const char *key, const char *value, void *cookie), 
+                  void *cookie)
+{
+    return 0;
+}
+
+#endif
diff --git a/package/utils/adbd/src/libcutils/qtaguid.c b/package/utils/adbd/src/libcutils/qtaguid.c
new file mode 100644
index 0000000..00e211c
--- /dev/null
+++ b/package/utils/adbd/src/libcutils/qtaguid.c
@@ -0,0 +1,176 @@
+/*
+** Copyright 2011, 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 LOG_NDEBUG 0
+
+#define LOG_TAG "qtaguid"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <cutils/qtaguid.h>
+#include <log/log.h>
+
+static const char* CTRL_PROCPATH = "/proc/net/xt_qtaguid/ctrl";
+static const int CTRL_MAX_INPUT_LEN = 128;
+static const char *GLOBAL_PACIFIER_PARAM = "/sys/module/xt_qtaguid/parameters/passive";
+static const char *TAG_PACIFIER_PARAM = "/sys/module/xt_qtaguid/parameters/tag_tracking_passive";
+
+/*
+ * One per proccess.
+ * Once the device is open, this process will have its socket tags tracked.
+ * And on exit or untimely death, all socket tags will be removed.
+ * A process can only open /dev/xt_qtaguid once.
+ * It should not close it unless it is really done with all the socket tags.
+ * Failure to open it will be visible when socket tagging will be attempted.
+ */
+static int resTrackFd = -1;
+pthread_once_t resTrackInitDone = PTHREAD_ONCE_INIT;
+
+/* Only call once per process. */
+void qtaguid_resTrack(void) {
+    resTrackFd = TEMP_FAILURE_RETRY(open("/dev/xt_qtaguid", O_RDONLY));
+    if (resTrackFd >=0) {
+        TEMP_FAILURE_RETRY(fcntl(resTrackFd, F_SETFD, FD_CLOEXEC));
+    }
+}
+
+/*
+ * Returns:
+ *   0 on success.
+ *   -errno on failure.
+ */
+static int write_ctrl(const char *cmd) {
+    int fd, res, savedErrno;
+
+    ALOGV("write_ctrl(%s)", cmd);
+
+    fd = TEMP_FAILURE_RETRY(open(CTRL_PROCPATH, O_WRONLY));
+    if (fd < 0) {
+        return -errno;
+    }
+
+    res = TEMP_FAILURE_RETRY(write(fd, cmd, strlen(cmd)));
+    if (res < 0) {
+        savedErrno = errno;
+    } else {
+        savedErrno = 0;
+    }
+    if (res < 0) {
+        ALOGI("Failed write_ctrl(%s) res=%d errno=%d", cmd, res, savedErrno);
+    }
+    close(fd);
+    return -savedErrno;
+}
+
+static int write_param(const char *param_path, const char *value) {
+    int param_fd;
+    int res;
+
+    param_fd = TEMP_FAILURE_RETRY(open(param_path, O_WRONLY));
+    if (param_fd < 0) {
+        return -errno;
+    }
+    res = TEMP_FAILURE_RETRY(write(param_fd, value, strlen(value)));
+    if (res < 0) {
+        return -errno;
+    }
+    close(param_fd);
+    return 0;
+}
+
+int qtaguid_tagSocket(int sockfd, int tag, uid_t uid) {
+    char lineBuf[CTRL_MAX_INPUT_LEN];
+    int res;
+    uint64_t kTag = ((uint64_t)tag << 32);
+
+    pthread_once(&resTrackInitDone, qtaguid_resTrack);
+
+    snprintf(lineBuf, sizeof(lineBuf), "t %d %" PRIu64 " %d", sockfd, kTag, uid);
+
+    ALOGV("Tagging socket %d with tag %" PRIx64 "{%u,0} for uid %d", sockfd, kTag, tag, uid);
+
+    res = write_ctrl(lineBuf);
+    if (res < 0) {
+        ALOGI("Tagging socket %d with tag %" PRIx64 "(%d) for uid %d failed errno=%d",
+             sockfd, kTag, tag, uid, res);
+    }
+
+    return res;
+}
+
+int qtaguid_untagSocket(int sockfd) {
+    char lineBuf[CTRL_MAX_INPUT_LEN];
+    int res;
+
+    ALOGV("Untagging socket %d", sockfd);
+
+    snprintf(lineBuf, sizeof(lineBuf), "u %d", sockfd);
+    res = write_ctrl(lineBuf);
+    if (res < 0) {
+        ALOGI("Untagging socket %d failed errno=%d", sockfd, res);
+    }
+
+    return res;
+}
+
+int qtaguid_setCounterSet(int counterSetNum, uid_t uid) {
+    char lineBuf[CTRL_MAX_INPUT_LEN];
+    int res;
+
+    ALOGV("Setting counters to set %d for uid %d", counterSetNum, uid);
+
+    snprintf(lineBuf, sizeof(lineBuf), "s %d %d", counterSetNum, uid);
+    res = write_ctrl(lineBuf);
+    return res;
+}
+
+int qtaguid_deleteTagData(int tag, uid_t uid) {
+    char lineBuf[CTRL_MAX_INPUT_LEN];
+    int cnt = 0, res = 0;
+    uint64_t kTag = (uint64_t)tag << 32;
+
+    ALOGV("Deleting tag data with tag %" PRIx64 "{%d,0} for uid %d", kTag, tag, uid);
+
+    pthread_once(&resTrackInitDone, qtaguid_resTrack);
+
+    snprintf(lineBuf, sizeof(lineBuf), "d %" PRIu64 " %d", kTag, uid);
+    res = write_ctrl(lineBuf);
+    if (res < 0) {
+        ALOGI("Deleting tag data with tag %" PRIx64 "/%d for uid %d failed with cnt=%d errno=%d",
+             kTag, tag, uid, cnt, errno);
+    }
+
+    return res;
+}
+
+int qtaguid_setPacifier(int on) {
+    const char *value;
+
+    value = on ? "Y" : "N";
+    if (write_param(GLOBAL_PACIFIER_PARAM, value) < 0) {
+        return -errno;
+    }
+    if (write_param(TAG_PACIFIER_PARAM, value) < 0) {
+        return -errno;
+    }
+    return 0;
+}
diff --git a/package/utils/adbd/src/libcutils/record_stream.c b/package/utils/adbd/src/libcutils/record_stream.c
new file mode 100644
index 0000000..6994904
--- /dev/null
+++ b/package/utils/adbd/src/libcutils/record_stream.c
@@ -0,0 +1,186 @@
+/* libs/cutils/record_stream.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.
+*/
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <assert.h>
+#include <errno.h>
+#include <cutils/record_stream.h>
+#include <string.h>
+#include <stdint.h>
+#ifdef HAVE_WINSOCK
+#include <winsock2.h>   /* for ntohl */
+#else
+#include <netinet/in.h>
+#endif
+
+#define HEADER_SIZE 4
+
+struct RecordStream {
+    int fd;
+    size_t maxRecordLen;
+
+    unsigned char *buffer;
+
+    unsigned char *unconsumed;
+    unsigned char *read_end;
+    unsigned char *buffer_end;
+};
+
+
+extern RecordStream *record_stream_new(int fd, size_t maxRecordLen)
+{
+    RecordStream *ret;
+
+    assert (maxRecordLen <= 0xffff);
+
+    ret = (RecordStream *)calloc(1, sizeof(RecordStream));
+
+    ret->fd = fd;
+    ret->maxRecordLen = maxRecordLen;
+    ret->buffer = (unsigned char *)malloc (maxRecordLen + HEADER_SIZE);
+    
+    ret->unconsumed = ret->buffer;
+    ret->read_end = ret->buffer;
+    ret->buffer_end = ret->buffer + maxRecordLen + HEADER_SIZE;
+
+    return ret;
+}
+
+
+extern void record_stream_free(RecordStream *rs)
+{
+    free(rs->buffer);
+    free(rs);
+}
+
+
+/* returns NULL; if there isn't a full record in the buffer */
+static unsigned char * getEndOfRecord (unsigned char *p_begin,
+                                            unsigned char *p_end)
+{
+    size_t len;
+    unsigned char * p_ret;
+
+    if (p_end < p_begin + HEADER_SIZE) {
+        return NULL;
+    }
+
+    //First four bytes are length
+    len = ntohl(*((uint32_t *)p_begin));
+
+    p_ret = p_begin + HEADER_SIZE + len;
+
+    if (p_end < p_ret) {
+        return NULL;
+    }
+
+    return p_ret;
+}
+
+static void *getNextRecord (RecordStream *p_rs, size_t *p_outRecordLen)
+{
+    unsigned char *record_start, *record_end;
+
+    record_end = getEndOfRecord (p_rs->unconsumed, p_rs->read_end);
+
+    if (record_end != NULL) {
+        /* one full line in the buffer */
+        record_start = p_rs->unconsumed + HEADER_SIZE;
+        p_rs->unconsumed = record_end;
+
+        *p_outRecordLen = record_end - record_start;
+
+        return record_start;
+    }
+
+    return NULL;
+}
+
+/**
+ * Reads the next record from stream fd
+ * Records are prefixed by a 16-bit big endian length value
+ * Records may not be larger than maxRecordLen
+ *
+ * Doesn't guard against EINTR
+ *
+ * p_outRecord and p_outRecordLen may not be NULL
+ *
+ * Return 0 on success, -1 on fail
+ * Returns 0 with *p_outRecord set to NULL on end of stream
+ * Returns -1 / errno = EAGAIN if it needs to read again
+ */
+int record_stream_get_next (RecordStream *p_rs, void ** p_outRecord, 
+                                    size_t *p_outRecordLen)
+{
+    void *ret;
+
+    ssize_t countRead;
+
+    /* is there one record already in the buffer? */
+    ret = getNextRecord (p_rs, p_outRecordLen);
+
+    if (ret != NULL) {
+        *p_outRecord = ret;
+        return 0;
+    }
+
+    // if the buffer is full and we don't have a full record
+    if (p_rs->unconsumed == p_rs->buffer 
+        && p_rs->read_end == p_rs->buffer_end
+    ) {
+        // this should never happen
+        //ALOGE("max record length exceeded\n");
+        assert (0);
+        errno = EFBIG;
+        return -1;
+    }
+
+    if (p_rs->unconsumed != p_rs->buffer) {
+        // move remainder to the beginning of the buffer
+        size_t toMove;
+
+        toMove = p_rs->read_end - p_rs->unconsumed;
+        if (toMove) {
+            memmove(p_rs->buffer, p_rs->unconsumed, toMove);
+        }
+
+        p_rs->read_end = p_rs->buffer + toMove;
+        p_rs->unconsumed = p_rs->buffer;
+    }
+
+    countRead = read (p_rs->fd, p_rs->read_end, p_rs->buffer_end - p_rs->read_end);
+
+    if (countRead <= 0) {
+        /* note: end-of-stream drops through here too */
+        *p_outRecord = NULL;
+        return countRead;
+    }
+
+    p_rs->read_end += countRead;
+
+    ret = getNextRecord (p_rs, p_outRecordLen);
+
+    if (ret == NULL) {
+        /* not enough of a buffer to for a whole command */
+        errno = EAGAIN;
+        return -1;
+    }
+
+    *p_outRecord = ret;        
+    return 0;
+}
diff --git a/package/utils/adbd/src/libcutils/sched_policy.c b/package/utils/adbd/src/libcutils/sched_policy.c
new file mode 100644
index 0000000..fa0792f
--- /dev/null
+++ b/package/utils/adbd/src/libcutils/sched_policy.c
@@ -0,0 +1,369 @@
+/*
+** Copyright 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.
+*/
+
+#define LOG_TAG "SchedPolicy"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <cutils/sched_policy.h>
+#include <log/log.h>
+
+#define UNUSED __attribute__((__unused__))
+
+/* Re-map SP_DEFAULT to the system default policy, and leave other values unchanged.
+ * Call this any place a SchedPolicy is used as an input parameter.
+ * Returns the possibly re-mapped policy.
+ */
+static inline SchedPolicy _policy(SchedPolicy p)
+{
+   return p == SP_DEFAULT ? SP_SYSTEM_DEFAULT : p;
+}
+
+#if defined(HAVE_ANDROID_OS) && defined(HAVE_SCHED_H) && defined(HAVE_PTHREADS)
+
+#include <linux/prctl.h>
+#include <sched.h>
+#include <pthread.h>
+
+#ifndef SCHED_NORMAL
+  #define SCHED_NORMAL 0
+#endif
+
+#ifndef SCHED_BATCH
+  #define SCHED_BATCH 3
+#endif
+
+#define POLICY_DEBUG 0
+
+#define CAN_SET_SP_SYSTEM 0 // non-zero means to implement set_sched_policy(tid, SP_SYSTEM)
+
+// timer slack value in nS enforced when the thread moves to background
+#define TIMER_SLACK_BG 40000000
+
+static pthread_once_t the_once = PTHREAD_ONCE_INIT;
+
+static int __sys_supports_schedgroups = -1;
+
+// File descriptors open to /dev/cpuctl/../tasks, setup by initialize, or -1 on error.
+static int bg_cgroup_fd = -1;
+static int fg_cgroup_fd = -1;
+#if CAN_SET_SP_SYSTEM
+static int system_cgroup_fd = -1;
+#endif
+
+/* Add tid to the scheduling group defined by the policy */
+static int add_tid_to_cgroup(int tid, SchedPolicy policy)
+{
+    int fd;
+
+    switch (policy) {
+    case SP_BACKGROUND:
+        fd = bg_cgroup_fd;
+        break;
+    case SP_FOREGROUND:
+    case SP_AUDIO_APP:
+    case SP_AUDIO_SYS:
+        fd = fg_cgroup_fd;
+        break;
+#if CAN_SET_SP_SYSTEM
+    case SP_SYSTEM:
+        fd = system_cgroup_fd;
+        break;
+#endif
+    default:
+        fd = -1;
+        break;
+    }
+
+    if (fd < 0) {
+        SLOGE("add_tid_to_cgroup failed; policy=%d\n", policy);
+        return -1;
+    }
+
+    // specialized itoa -- works for tid > 0
+    char text[22];
+    char *end = text + sizeof(text) - 1;
+    char *ptr = end;
+    *ptr = '\0';
+    while (tid > 0) {
+        *--ptr = '0' + (tid % 10);
+        tid = tid / 10;
+    }
+
+    if (write(fd, ptr, end - ptr) < 0) {
+        /*
+         * If the thread is in the process of exiting,
+         * don't flag an error
+         */
+        if (errno == ESRCH)
+                return 0;
+        SLOGW("add_tid_to_cgroup failed to write '%s' (%s); policy=%d\n",
+              ptr, strerror(errno), policy);
+        return -1;
+    }
+
+    return 0;
+}
+
+static void __initialize(void) {
+    char* filename;
+    if (!access("/dev/cpuctl/tasks", F_OK)) {
+        __sys_supports_schedgroups = 1;
+
+#if CAN_SET_SP_SYSTEM
+        filename = "/dev/cpuctl/tasks";
+        system_cgroup_fd = open(filename, O_WRONLY | O_CLOEXEC);
+        if (system_cgroup_fd < 0) {
+            SLOGV("open of %s failed: %s\n", filename, strerror(errno));
+        }
+#endif
+
+        filename = "/dev/cpuctl/apps/tasks";
+        fg_cgroup_fd = open(filename, O_WRONLY | O_CLOEXEC);
+        if (fg_cgroup_fd < 0) {
+            SLOGE("open of %s failed: %s\n", filename, strerror(errno));
+        }
+
+        filename = "/dev/cpuctl/apps/bg_non_interactive/tasks";
+        bg_cgroup_fd = open(filename, O_WRONLY | O_CLOEXEC);
+        if (bg_cgroup_fd < 0) {
+            SLOGE("open of %s failed: %s\n", filename, strerror(errno));
+        }
+    } else {
+        __sys_supports_schedgroups = 0;
+    }
+}
+
+/*
+ * Try to get the scheduler group.
+ *
+ * The data from /proc/<pid>/cgroup looks (something) like:
+ *  2:cpu:/bg_non_interactive
+ *  1:cpuacct:/
+ *
+ * We return the part after the "/", which will be an empty string for
+ * the default cgroup.  If the string is longer than "bufLen", the string
+ * will be truncated.
+ */
+static int getSchedulerGroup(int tid, char* buf, size_t bufLen)
+{
+#ifdef HAVE_ANDROID_OS
+    char pathBuf[32];
+    char lineBuf[256];
+    FILE *fp;
+
+    snprintf(pathBuf, sizeof(pathBuf), "/proc/%d/cgroup", tid);
+    if (!(fp = fopen(pathBuf, "r"))) {
+        return -1;
+    }
+
+    while(fgets(lineBuf, sizeof(lineBuf) -1, fp)) {
+        char *next = lineBuf;
+        char *subsys;
+        char *grp;
+        size_t len;
+
+        /* Junk the first field */
+        if (!strsep(&next, ":")) {
+            goto out_bad_data;
+        }
+
+        if (!(subsys = strsep(&next, ":"))) {
+            goto out_bad_data;
+        }
+
+        if (strcmp(subsys, "cpu")) {
+            /* Not the subsys we're looking for */
+            continue;
+        }
+
+        if (!(grp = strsep(&next, ":"))) {
+            goto out_bad_data;
+        }
+        grp++; /* Drop the leading '/' */
+        len = strlen(grp);
+        grp[len-1] = '\0'; /* Drop the trailing '\n' */
+
+        if (bufLen <= len) {
+            len = bufLen - 1;
+        }
+        strncpy(buf, grp, len);
+        buf[len] = '\0';
+        fclose(fp);
+        return 0;
+    }
+
+    SLOGE("Failed to find cpu subsys");
+    fclose(fp);
+    return -1;
+ out_bad_data:
+    SLOGE("Bad cgroup data {%s}", lineBuf);
+    fclose(fp);
+    return -1;
+#else
+    errno = ENOSYS;
+    return -1;
+#endif
+}
+
+int get_sched_policy(int tid, SchedPolicy *policy)
+{
+#ifdef HAVE_GETTID
+    if (tid == 0) {
+        tid = gettid();
+    }
+#endif
+    pthread_once(&the_once, __initialize);
+
+    if (__sys_supports_schedgroups) {
+        char grpBuf[32];
+        if (getSchedulerGroup(tid, grpBuf, sizeof(grpBuf)) < 0)
+            return -1;
+        if (grpBuf[0] == '\0') {
+            *policy = SP_SYSTEM;
+        } else if (!strcmp(grpBuf, "apps/bg_non_interactive")) {
+            *policy = SP_BACKGROUND;
+        } else if (!strcmp(grpBuf, "apps")) {
+            *policy = SP_FOREGROUND;
+        } else {
+            errno = ERANGE;
+            return -1;
+        }
+    } else {
+        int rc = sched_getscheduler(tid);
+        if (rc < 0)
+            return -1;
+        else if (rc == SCHED_NORMAL)
+            *policy = SP_FOREGROUND;
+        else if (rc == SCHED_BATCH)
+            *policy = SP_BACKGROUND;
+        else {
+            errno = ERANGE;
+            return -1;
+        }
+    }
+    return 0;
+}
+
+int set_sched_policy(int tid, SchedPolicy policy)
+{
+#ifdef HAVE_GETTID
+    if (tid == 0) {
+        tid = gettid();
+    }
+#endif
+    policy = _policy(policy);
+    pthread_once(&the_once, __initialize);
+
+#if POLICY_DEBUG
+    char statfile[64];
+    char statline[1024];
+    char thread_name[255];
+    int fd;
+
+    sprintf(statfile, "/proc/%d/stat", tid);
+    memset(thread_name, 0, sizeof(thread_name));
+
+    fd = open(statfile, O_RDONLY);
+    if (fd >= 0) {
+        int rc = read(fd, statline, 1023);
+        close(fd);
+        statline[rc] = 0;
+        char *p = statline;
+        char *q;
+
+        for (p = statline; *p != '('; p++);
+        p++;
+        for (q = p; *q != ')'; q++);
+
+        strncpy(thread_name, p, (q-p));
+    }
+    switch (policy) {
+    case SP_BACKGROUND:
+        SLOGD("vvv tid %d (%s)", tid, thread_name);
+        break;
+    case SP_FOREGROUND:
+    case SP_AUDIO_APP:
+    case SP_AUDIO_SYS:
+        SLOGD("^^^ tid %d (%s)", tid, thread_name);
+        break;
+    case SP_SYSTEM:
+        SLOGD("/// tid %d (%s)", tid, thread_name);
+        break;
+    default:
+        SLOGD("??? tid %d (%s)", tid, thread_name);
+        break;
+    }
+#endif
+
+    if (__sys_supports_schedgroups) {
+        if (add_tid_to_cgroup(tid, policy)) {
+            if (errno != ESRCH && errno != ENOENT)
+                return -errno;
+        }
+    } else {
+        struct sched_param param;
+
+        param.sched_priority = 0;
+        sched_setscheduler(tid,
+                           (policy == SP_BACKGROUND) ?
+                            SCHED_BATCH : SCHED_NORMAL,
+                           &param);
+    }
+
+    prctl(PR_SET_TIMERSLACK_PID, policy == SP_BACKGROUND ? TIMER_SLACK_BG : 0, tid);
+
+    return 0;
+}
+
+#else
+
+/* Stubs for non-Android targets. */
+
+int set_sched_policy(int tid UNUSED, SchedPolicy policy UNUSED)
+{
+    return 0;
+}
+
+int get_sched_policy(int tid UNUSED, SchedPolicy *policy)
+{
+    *policy = SP_SYSTEM_DEFAULT;
+    return 0;
+}
+
+#endif
+
+const char *get_sched_policy_name(SchedPolicy policy)
+{
+    policy = _policy(policy);
+    static const char * const strings[SP_CNT] = {
+       [SP_BACKGROUND] = "bg",
+       [SP_FOREGROUND] = "fg",
+       [SP_SYSTEM]     = "  ",
+       [SP_AUDIO_APP]  = "aa",
+       [SP_AUDIO_SYS]  = "as",
+    };
+    if ((policy < SP_CNT) && (strings[policy] != NULL))
+        return strings[policy];
+    else
+        return "error";
+}
+
diff --git a/package/utils/adbd/src/libcutils/socket_inaddr_any_server.c b/package/utils/adbd/src/libcutils/socket_inaddr_any_server.c
new file mode 100644
index 0000000..6c849de
--- /dev/null
+++ b/package/utils/adbd/src/libcutils/socket_inaddr_any_server.c
@@ -0,0 +1,68 @@
+/*
+** 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.
+*/
+
+#include <errno.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifndef HAVE_WINSOCK
+#include <sys/socket.h>
+#include <sys/select.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#endif
+
+#include <cutils/sockets.h>
+
+#define LISTEN_BACKLOG 4
+
+/* open listen() port on any interface */
+int socket_inaddr_any_server(int port, int type)
+{
+    struct sockaddr_in addr;
+    int s, n;
+
+    memset(&addr, 0, sizeof(addr));
+    addr.sin_family = AF_INET;
+    addr.sin_port = htons(port);
+    addr.sin_addr.s_addr = htonl(INADDR_ANY);
+
+    s = socket(AF_INET, type, 0);
+    if(s < 0) return -1;
+
+    n = 1;
+    setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char *) &n, sizeof(n));
+
+    if(bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+        close(s);
+        return -1;
+    }
+
+    if (type == SOCK_STREAM) {
+        int ret;
+
+        ret = listen(s, LISTEN_BACKLOG);
+
+        if (ret < 0) {
+            close(s);
+            return -1; 
+        }
+    }
+
+    return s;
+}
diff --git a/package/utils/adbd/src/libcutils/socket_local.h b/package/utils/adbd/src/libcutils/socket_local.h
new file mode 100644
index 0000000..45b9856
--- /dev/null
+++ b/package/utils/adbd/src/libcutils/socket_local.h
@@ -0,0 +1,39 @@
+/*
+ * 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 __SOCKET_LOCAL_H
+#define __SOCKET_LOCAL_H
+
+#define FILESYSTEM_SOCKET_PREFIX "/tmp/" 
+#define ANDROID_RESERVED_SOCKET_PREFIX "/dev/socket/"
+
+/*
+ * Set up a given sockaddr_un, to have it refer to the given
+ * name in the given namespace. The namespace must be one
+ * of <code>ANDROID_SOCKET_NAMESPACE_ABSTRACT</code>,
+ * <code>ANDROID_SOCKET_NAMESPACE_RESERVED</code>, or
+ * <code>ANDROID_SOCKET_NAMESPACE_FILESYSTEM</code>. Upon success,
+ * the pointed at sockaddr_un is filled in and the pointed at
+ * socklen_t is set to indicate the final length. This function
+ * will fail if the namespace is invalid (not one of the indicated
+ * constants) or if the name is too long.
+ * 
+ * @return 0 on success or -1 on failure
+ */ 
+int socket_make_sockaddr_un(const char *name, int namespaceId, 
+        struct sockaddr_un *p_addr, socklen_t *alen);
+
+#endif
diff --git a/package/utils/adbd/src/libcutils/socket_local_client.c b/package/utils/adbd/src/libcutils/socket_local_client.c
new file mode 100644
index 0000000..ddcc2da
--- /dev/null
+++ b/package/utils/adbd/src/libcutils/socket_local_client.c
@@ -0,0 +1,168 @@
+/*
+ * 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.
+ */
+
+#include <errno.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <cutils/sockets.h>
+
+#ifdef HAVE_WINSOCK
+
+int socket_local_client(const char *name, int namespaceId, int type)
+{
+    errno = ENOSYS;
+    return -1;
+}
+
+#else /* !HAVE_WINSOCK */
+
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/select.h>
+#include <sys/types.h>
+
+#include "socket_local.h"
+
+#define UNUSED __attribute__((unused))
+
+#define LISTEN_BACKLOG 4
+
+/* Documented in header file. */
+int socket_make_sockaddr_un(const char *name, int namespaceId, 
+        struct sockaddr_un *p_addr, socklen_t *alen)
+{
+    memset (p_addr, 0, sizeof (*p_addr));
+    size_t namelen;
+
+    switch (namespaceId) {
+        case ANDROID_SOCKET_NAMESPACE_ABSTRACT:
+#ifdef HAVE_LINUX_LOCAL_SOCKET_NAMESPACE
+            namelen  = strlen(name);
+
+            // Test with length +1 for the *initial* '\0'.
+            if ((namelen + 1) > sizeof(p_addr->sun_path)) {
+                goto error;
+            }
+
+            /*
+             * Note: The path in this case is *not* supposed to be
+             * '\0'-terminated. ("man 7 unix" for the gory details.)
+             */
+            
+            p_addr->sun_path[0] = 0;
+            memcpy(p_addr->sun_path + 1, name, namelen);
+#else /*HAVE_LINUX_LOCAL_SOCKET_NAMESPACE*/
+            /* this OS doesn't have the Linux abstract namespace */
+
+            namelen = strlen(name) + strlen(FILESYSTEM_SOCKET_PREFIX);
+            /* unix_path_max appears to be missing on linux */
+            if (namelen > sizeof(*p_addr) 
+                    - offsetof(struct sockaddr_un, sun_path) - 1) {
+                goto error;
+            }
+
+            strcpy(p_addr->sun_path, FILESYSTEM_SOCKET_PREFIX);
+            strcat(p_addr->sun_path, name);
+#endif /*HAVE_LINUX_LOCAL_SOCKET_NAMESPACE*/
+        break;
+
+        case ANDROID_SOCKET_NAMESPACE_RESERVED:
+            namelen = strlen(name) + strlen(ANDROID_RESERVED_SOCKET_PREFIX);
+            /* unix_path_max appears to be missing on linux */
+            if (namelen > sizeof(*p_addr) 
+                    - offsetof(struct sockaddr_un, sun_path) - 1) {
+                goto error;
+            }
+
+            strcpy(p_addr->sun_path, ANDROID_RESERVED_SOCKET_PREFIX);
+            strcat(p_addr->sun_path, name);
+        break;
+
+        case ANDROID_SOCKET_NAMESPACE_FILESYSTEM:
+            namelen = strlen(name);
+            /* unix_path_max appears to be missing on linux */
+            if (namelen > sizeof(*p_addr) 
+                    - offsetof(struct sockaddr_un, sun_path) - 1) {
+                goto error;
+            }
+
+            strcpy(p_addr->sun_path, name);
+        break;
+        default:
+            // invalid namespace id
+            return -1;
+    }
+
+    p_addr->sun_family = AF_LOCAL;
+    *alen = namelen + offsetof(struct sockaddr_un, sun_path) + 1;
+    return 0;
+error:
+    return -1;
+}
+
+/**
+ * connect to peer named "name" on fd
+ * returns same fd or -1 on error.
+ * fd is not closed on error. that's your job.
+ * 
+ * Used by AndroidSocketImpl
+ */
+int socket_local_client_connect(int fd, const char *name, int namespaceId, 
+        int type UNUSED)
+{
+    struct sockaddr_un addr;
+    socklen_t alen;
+    int err;
+
+    err = socket_make_sockaddr_un(name, namespaceId, &addr, &alen);
+
+    if (err < 0) {
+        goto error;
+    }
+
+    if(connect(fd, (struct sockaddr *) &addr, alen) < 0) {
+        goto error;
+    }
+
+    return fd;
+
+error:
+    return -1;
+}
+
+/** 
+ * connect to peer named "name"
+ * returns fd or -1 on error
+ */
+int socket_local_client(const char *name, int namespaceId, int type)
+{
+    int s;
+
+    s = socket(AF_LOCAL, type, 0);
+    if(s < 0) return -1;
+
+    if ( 0 > socket_local_client_connect(s, name, namespaceId, type)) {
+        close(s);
+        return -1;
+    }
+
+    return s;
+}
+
+#endif /* !HAVE_WINSOCK */
diff --git a/package/utils/adbd/src/libcutils/socket_local_server.c b/package/utils/adbd/src/libcutils/socket_local_server.c
new file mode 100644
index 0000000..7628fe4
--- /dev/null
+++ b/package/utils/adbd/src/libcutils/socket_local_server.c
@@ -0,0 +1,126 @@
+/* libs/cutils/socket_local_server.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.
+*/
+
+#include <cutils/sockets.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stddef.h>
+
+#ifdef HAVE_WINSOCK
+
+int socket_local_server(const char *name, int namespaceId, int type)
+{
+    errno = ENOSYS;
+    return -1;
+}
+
+#else /* !HAVE_WINSOCK */
+
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/select.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+
+#include "socket_local.h"
+
+#define LISTEN_BACKLOG 4
+
+/* Only the bottom bits are really the socket type; there are flags too. */
+#define SOCK_TYPE_MASK 0xf
+
+/**
+ * Binds a pre-created socket(AF_LOCAL) 's' to 'name'
+ * returns 's' on success, -1 on fail
+ *
+ * Does not call listen()
+ */
+int socket_local_server_bind(int s, const char *name, int namespaceId)
+{
+    struct sockaddr_un addr;
+    socklen_t alen;
+    int n;
+    int err;
+
+    err = socket_make_sockaddr_un(name, namespaceId, &addr, &alen);
+
+    if (err < 0) {
+        return -1;
+    }
+
+    /* basically: if this is a filesystem path, unlink first */
+#ifndef HAVE_LINUX_LOCAL_SOCKET_NAMESPACE
+    if (1) {
+#else
+    if (namespaceId == ANDROID_SOCKET_NAMESPACE_RESERVED
+        || namespaceId == ANDROID_SOCKET_NAMESPACE_FILESYSTEM) {
+#endif
+        /*ignore ENOENT*/
+        unlink(addr.sun_path);
+    }
+
+    n = 1;
+    setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &n, sizeof(n));
+
+    if(bind(s, (struct sockaddr *) &addr, alen) < 0) {
+        return -1;
+    }
+
+    return s;
+
+}
+
+
+/** Open a server-side UNIX domain datagram socket in the Linux non-filesystem 
+ *  namespace
+ *
+ *  Returns fd on success, -1 on fail
+ */
+
+int socket_local_server(const char *name, int namespace, int type)
+{
+    int err;
+    int s;
+    
+    s = socket(AF_LOCAL, type, 0);
+    if (s < 0) return -1;
+
+    err = socket_local_server_bind(s, name, namespace);
+
+    if (err < 0) {
+        close(s);
+        return -1;
+    }
+
+    if ((type & SOCK_TYPE_MASK) == SOCK_STREAM) {
+        int ret;
+
+        ret = listen(s, LISTEN_BACKLOG);
+
+        if (ret < 0) {
+            close(s);
+            return -1;
+        }
+    }
+
+    return s;
+}
+
+#endif /* !HAVE_WINSOCK */
diff --git a/package/utils/adbd/src/libcutils/socket_loopback_client.c b/package/utils/adbd/src/libcutils/socket_loopback_client.c
new file mode 100644
index 0000000..9aed7b7
--- /dev/null
+++ b/package/utils/adbd/src/libcutils/socket_loopback_client.c
@@ -0,0 +1,57 @@
+/*
+** 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.
+*/
+
+#include <errno.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifndef HAVE_WINSOCK
+#include <sys/socket.h>
+#include <sys/select.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#endif
+
+#include <cutils/sockets.h>
+
+/* Connect to port on the loopback IP interface. type is
+ * SOCK_STREAM or SOCK_DGRAM. 
+ * return is a file descriptor or -1 on error
+ */
+int socket_loopback_client(int port, int type)
+{
+    struct sockaddr_in addr;
+    int s;
+
+    memset(&addr, 0, sizeof(addr));
+    addr.sin_family = AF_INET;
+    addr.sin_port = htons(port);
+    addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+
+    s = socket(AF_INET, type, 0);
+    if(s < 0) return -1;
+
+    if(connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+        close(s);
+        return -1;
+    }
+
+    return s;
+
+}
+
diff --git a/package/utils/adbd/src/libcutils/socket_loopback_server.c b/package/utils/adbd/src/libcutils/socket_loopback_server.c
new file mode 100644
index 0000000..71afce7
--- /dev/null
+++ b/package/utils/adbd/src/libcutils/socket_loopback_server.c
@@ -0,0 +1,69 @@
+/*
+** 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.
+*/
+
+#include <errno.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define LISTEN_BACKLOG 4
+
+#ifndef HAVE_WINSOCK
+#include <sys/socket.h>
+#include <sys/select.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#endif
+
+#include <cutils/sockets.h>
+
+/* open listen() port on loopback interface */
+int socket_loopback_server(int port, int type)
+{
+    struct sockaddr_in addr;
+    int s, n;
+
+    memset(&addr, 0, sizeof(addr));
+    addr.sin_family = AF_INET;
+    addr.sin_port = htons(port);
+    addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+
+    s = socket(AF_INET, type, 0);
+    if(s < 0) return -1;
+
+    n = 1;
+    setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char *) &n, sizeof(n));
+
+    if(bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+        close(s);
+        return -1;
+    }
+
+    if (type == SOCK_STREAM) {
+        int ret;
+
+        ret = listen(s, LISTEN_BACKLOG);
+
+        if (ret < 0) {
+            close(s);
+            return -1; 
+        }
+    }
+
+    return s;
+}
+
diff --git a/package/utils/adbd/src/libcutils/socket_network_client.c b/package/utils/adbd/src/libcutils/socket_network_client.c
new file mode 100644
index 0000000..8790786
--- /dev/null
+++ b/package/utils/adbd/src/libcutils/socket_network_client.c
@@ -0,0 +1,126 @@
+/*
+** 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.
+*/
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/socket.h>
+#include <sys/select.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <netdb.h>
+
+#include <cutils/sockets.h>
+
+/* Connect to port on the IP interface. type is
+ * SOCK_STREAM or SOCK_DGRAM. 
+ * return is a file descriptor or -1 on error
+ */
+int socket_network_client(const char *host, int port, int type)
+{
+    return socket_network_client_timeout(host, port, type, 0);
+}
+
+/* Connect to port on the IP interface. type is SOCK_STREAM or SOCK_DGRAM.
+ * timeout in seconds return is a file descriptor or -1 on error
+ */
+int socket_network_client_timeout(const char *host, int port, int type, int timeout)
+{
+    struct hostent *hp;
+    struct sockaddr_in addr;
+    //socklen_t alen; // changed by feilv
+    int s;
+    int flags = 0, error = 0, ret = 0;
+    fd_set rset, wset;
+    socklen_t len = sizeof(error);
+    struct timeval ts;
+
+    ts.tv_sec = timeout;
+    ts.tv_usec = 0;
+
+    hp = gethostbyname(host);
+    if (hp == 0) return -1;
+
+    memset(&addr, 0, sizeof(addr));
+    addr.sin_family = hp->h_addrtype;
+    addr.sin_port = htons(port);
+    memcpy(&addr.sin_addr, hp->h_addr, hp->h_length);
+
+    s = socket(hp->h_addrtype, type, 0);
+    if (s < 0) return -1;
+
+    if ((flags = fcntl(s, F_GETFL, 0)) < 0) {
+        close(s);
+        return -1;
+    }
+
+    if (fcntl(s, F_SETFL, flags | O_NONBLOCK) < 0) {
+        close(s);
+        return -1;
+    }
+
+    if ((ret = connect(s, (struct sockaddr *) &addr, sizeof(addr))) < 0) {
+        if (errno != EINPROGRESS) {
+            close(s);
+            return -1;
+        }
+    }
+
+    if (ret == 0)
+        goto done;
+
+    FD_ZERO(&rset);
+    FD_SET(s, &rset);
+    wset = rset;
+
+    if ((ret = select(s + 1, &rset, &wset, NULL, (timeout) ? &ts : NULL)) < 0) {
+        close(s);
+        return -1;
+    }
+    if (ret == 0) {   // we had a timeout
+        errno = ETIMEDOUT;
+        close(s);
+        return -1;
+    }
+
+    if (FD_ISSET(s, &rset) || FD_ISSET(s, &wset)) {
+        if (getsockopt(s, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
+            close(s);
+            return -1;
+        }
+    } else {
+        close(s);
+        return -1;
+    }
+
+    if (error) {  // check if we had a socket error
+        errno = error;
+        close(s);
+        return -1;
+    }
+
+done:
+    if (fcntl(s, F_SETFL, flags) < 0) {
+        close(s);
+        return -1;
+    }
+
+    return s;
+}
diff --git a/package/utils/adbd/src/libcutils/sockets.c b/package/utils/adbd/src/libcutils/sockets.c
new file mode 100644
index 0000000..15ede2b
--- /dev/null
+++ b/package/utils/adbd/src/libcutils/sockets.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2011 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 <cutils/sockets.h>
+#include <log/log.h>
+
+#ifdef HAVE_ANDROID_OS
+/* For the socket trust (credentials) check */
+#include <private/android_filesystem_config.h>
+#define __android_unused
+#else
+#define __android_unused __attribute__((__unused__))
+#endif
+
+bool socket_peer_is_trusted(int fd __android_unused)
+{
+#ifdef HAVE_ANDROID_OS
+    struct ucred cr;
+    socklen_t len = sizeof(cr);
+    int n = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cr, &len);
+
+    if (n != 0) {
+        ALOGE("could not get socket credentials: %s\n", strerror(errno));
+        return false;
+    }
+
+    if ((cr.uid != AID_ROOT) && (cr.uid != AID_SHELL)) {
+        ALOGE("untrusted userid on other end of socket: userid %d\n", cr.uid);
+        return false;
+    }
+#endif
+
+    return true;
+}
diff --git a/package/utils/adbd/src/libcutils/str_parms.c b/package/utils/adbd/src/libcutils/str_parms.c
new file mode 100644
index 0000000..dfe8c4b
--- /dev/null
+++ b/package/utils/adbd/src/libcutils/str_parms.c
@@ -0,0 +1,407 @@
+/*
+ * Copyright (C) 2011-2013 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 LOG_TAG "str_params"
+//#define LOG_NDEBUG 0
+
+#define _GNU_SOURCE 1
+#include <errno.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <cutils/hashmap.h>
+#include <cutils/memory.h>
+#include <cutils/str_parms.h>
+#include <log/log.h>
+
+#define UNUSED __attribute__((unused))
+
+struct str_parms {
+    Hashmap *map;
+};
+
+
+static bool str_eq(void *key_a, void *key_b)
+{
+    return !strcmp((const char *)key_a, (const char *)key_b);
+}
+
+/* use djb hash unless we find it inadequate */
+static int str_hash_fn(void *str)
+{
+    uint32_t hash = 5381;
+    char *p;
+
+    for (p = str; p && *p; p++)
+        hash = ((hash << 5) + hash) + *p;
+    return (int)hash;
+}
+
+struct str_parms *str_parms_create(void)
+{
+    struct str_parms *str_parms;
+
+    str_parms = calloc(1, sizeof(struct str_parms));
+    if (!str_parms)
+        return NULL;
+
+    str_parms->map = hashmapCreate(5, str_hash_fn, str_eq);
+    if (!str_parms->map)
+        goto err;
+
+    return str_parms;
+
+err:
+    free(str_parms);
+    return NULL;
+}
+
+struct remove_ctxt {
+    struct str_parms *str_parms;
+    const char *key;
+};
+
+static bool remove_pair(void *key, void *value, void *context)
+{
+    struct remove_ctxt *ctxt = context;
+    bool should_continue;
+
+    /*
+     * - if key is not supplied, then we are removing all entries,
+     *   so remove key and continue (i.e. return true)
+     * - if key is supplied and matches, then remove it and don't
+     *   continue (return false). Otherwise, return true and keep searching
+     *   for key.
+     *
+     */
+    if (!ctxt->key) {
+        should_continue = true;
+        goto do_remove;
+    } else if (!strcmp(ctxt->key, key)) {
+        should_continue = false;
+        goto do_remove;
+    }
+
+    return true;
+
+do_remove:
+    hashmapRemove(ctxt->str_parms->map, key);
+    free(key);
+    free(value);
+    return should_continue;
+}
+
+void str_parms_del(struct str_parms *str_parms, const char *key)
+{
+    struct remove_ctxt ctxt = {
+        .str_parms = str_parms,
+        .key = key,
+    };
+    hashmapForEach(str_parms->map, remove_pair, &ctxt);
+}
+
+void str_parms_destroy(struct str_parms *str_parms)
+{
+    struct remove_ctxt ctxt = {
+        .str_parms = str_parms,
+    };
+
+    hashmapForEach(str_parms->map, remove_pair, &ctxt);
+    hashmapFree(str_parms->map);
+    free(str_parms);
+}
+
+struct str_parms *str_parms_create_str(const char *_string)
+{
+    struct str_parms *str_parms;
+    char *str;
+    char *kvpair;
+    char *tmpstr;
+    int items = 0;
+
+    str_parms = str_parms_create();
+    if (!str_parms)
+        goto err_create_str_parms;
+
+    str = strdup(_string);
+    if (!str)
+        goto err_strdup;
+
+    ALOGV("%s: source string == '%s'\n", __func__, _string);
+
+    kvpair = strtok_r(str, ";", &tmpstr);
+    while (kvpair && *kvpair) {
+        char *eq = strchr(kvpair, '='); /* would love strchrnul */
+        char *value;
+        char *key;
+        void *old_val;
+
+        if (eq == kvpair)
+            goto next_pair;
+
+        if (eq) {
+            key = strndup(kvpair, eq - kvpair);
+            if (*(++eq))
+                value = strdup(eq);
+            else
+                value = strdup("");
+        } else {
+            key = strdup(kvpair);
+            value = strdup("");
+        }
+
+        /* if we replaced a value, free it */
+        old_val = hashmapPut(str_parms->map, key, value);
+        if (old_val) {
+            free(old_val);
+            free(key);
+        }
+
+        items++;
+next_pair:
+        kvpair = strtok_r(NULL, ";", &tmpstr);
+    }
+
+    if (!items)
+        ALOGV("%s: no items found in string\n", __func__);
+
+    free(str);
+
+    return str_parms;
+
+err_strdup:
+    str_parms_destroy(str_parms);
+err_create_str_parms:
+    return NULL;
+}
+
+int str_parms_add_str(struct str_parms *str_parms, const char *key,
+                      const char *value)
+{
+    void *tmp_key = NULL;
+    void *tmp_val = NULL;
+    void *old_val = NULL;
+
+    // strdup and hashmapPut both set errno on failure.
+    // Set errno to 0 so we can recognize whether anything went wrong.
+    int saved_errno = errno;
+    errno = 0;
+
+    tmp_key = strdup(key);
+    if (tmp_key == NULL) {
+        goto clean_up;
+    }
+
+    tmp_val = strdup(value);
+    if (tmp_val == NULL) {
+        goto clean_up;
+    }
+
+    old_val = hashmapPut(str_parms->map, tmp_key, tmp_val);
+    if (old_val == NULL) {
+        // Did hashmapPut fail?
+        if (errno == ENOMEM) {
+            goto clean_up;
+        }
+        // For new keys, hashmap takes ownership of tmp_key and tmp_val.
+        tmp_key = tmp_val = NULL;
+    } else {
+        // For existing keys, hashmap takes ownership of tmp_val.
+        // (It also gives up ownership of old_val.)
+        tmp_val = NULL;
+    }
+
+clean_up:
+    free(tmp_key);
+    free(tmp_val);
+    free(old_val);
+    int result = -errno;
+    errno = saved_errno;
+    return result;
+}
+
+int str_parms_add_int(struct str_parms *str_parms, const char *key, int value)
+{
+    char val_str[12];
+    int ret;
+
+    ret = snprintf(val_str, sizeof(val_str), "%d", value);
+    if (ret < 0)
+        return -EINVAL;
+
+    ret = str_parms_add_str(str_parms, key, val_str);
+    return ret;
+}
+
+int str_parms_add_float(struct str_parms *str_parms, const char *key,
+                        float value)
+{
+    char val_str[23];
+    int ret;
+
+    ret = snprintf(val_str, sizeof(val_str), "%.10f", value);
+    if (ret < 0)
+        return -EINVAL;
+
+    ret = str_parms_add_str(str_parms, key, val_str);
+    return ret;
+}
+
+int str_parms_has_key(struct str_parms *str_parms, const char *key) {
+    return hashmapGet(str_parms->map, (void *)key) != NULL;
+}
+
+int str_parms_get_str(struct str_parms *str_parms, const char *key, char *val,
+                      int len)
+{
+    char *value;
+
+    value = hashmapGet(str_parms->map, (void *)key);
+    if (value)
+        return strlcpy(val, value, len);
+
+    return -ENOENT;
+}
+
+int str_parms_get_int(struct str_parms *str_parms, const char *key, int *val)
+{
+    char *value;
+    char *end;
+
+    value = hashmapGet(str_parms->map, (void *)key);
+    if (!value)
+        return -ENOENT;
+
+    *val = (int)strtol(value, &end, 0);
+    if (*value != '\0' && *end == '\0')
+        return 0;
+
+    return -EINVAL;
+}
+
+int str_parms_get_float(struct str_parms *str_parms, const char *key,
+                        float *val)
+{
+    float out;
+    char *value;
+    char *end;
+
+    value = hashmapGet(str_parms->map, (void *)key);
+    if (!value)
+        return -ENOENT;
+
+    out = strtof(value, &end);
+    if (*value == '\0' || *end != '\0')
+        return -EINVAL;
+
+    *val = out;
+    return 0;
+}
+
+static bool combine_strings(void *key, void *value, void *context)
+{
+    char **old_str = context;
+    char *new_str;
+    int ret;
+
+    ret = asprintf(&new_str, "%s%s%s=%s",
+                   *old_str ? *old_str : "",
+                   *old_str ? ";" : "",
+                   (char *)key,
+                   (char *)value);
+    if (*old_str)
+        free(*old_str);
+
+    if (ret >= 0) {
+        *old_str = new_str;
+        return true;
+    }
+
+    *old_str = NULL;
+    return false;
+}
+
+char *str_parms_to_str(struct str_parms *str_parms)
+{
+    char *str = NULL;
+
+    if (hashmapSize(str_parms->map) > 0)
+        hashmapForEach(str_parms->map, combine_strings, &str);
+    else
+        str = strdup("");
+    return str;
+}
+
+static bool dump_entry(void *key, void *value, void *context UNUSED)
+{
+    ALOGI("key: '%s' value: '%s'\n", (char *)key, (char *)value);
+    return true;
+}
+
+void str_parms_dump(struct str_parms *str_parms)
+{
+    hashmapForEach(str_parms->map, dump_entry, str_parms);
+}
+
+#ifdef TEST_STR_PARMS
+static void test_str_parms_str(const char *str)
+{
+    struct str_parms *str_parms;
+    char *out_str;
+
+    str_parms = str_parms_create_str(str);
+    str_parms_add_str(str_parms, "dude", "woah");
+    str_parms_add_str(str_parms, "dude", "woah");
+    str_parms_del(str_parms, "dude");
+    str_parms_dump(str_parms);
+    out_str = str_parms_to_str(str_parms);
+    str_parms_destroy(str_parms);
+    ALOGI("%s: '%s' stringified is '%s'", __func__, str, out_str);
+    free(out_str);
+}
+
+int main(void)
+{
+    test_str_parms_str("");
+    test_str_parms_str(";");
+    test_str_parms_str("=");
+    test_str_parms_str("=;");
+    test_str_parms_str("=bar");
+    test_str_parms_str("=bar;");
+    test_str_parms_str("foo=");
+    test_str_parms_str("foo=;");
+    test_str_parms_str("foo=bar");
+    test_str_parms_str("foo=bar;");
+    test_str_parms_str("foo=bar;baz");
+    test_str_parms_str("foo=bar;baz=");
+    test_str_parms_str("foo=bar;baz=bat");
+    test_str_parms_str("foo=bar;baz=bat;");
+    test_str_parms_str("foo=bar;baz=bat;foo=bar");
+
+    // hashmapPut reports errors by setting errno to ENOMEM.
+    // Test that we're not confused by running in an environment where this is already true.
+    errno = ENOMEM;
+    test_str_parms_str("foo=bar;baz=");
+    if (errno != ENOMEM) {
+        abort();
+    }
+    test_str_parms_str("foo=bar;baz=");
+
+    return 0;
+}
+#endif
diff --git a/package/utils/adbd/src/libcutils/strdup16to8.c b/package/utils/adbd/src/libcutils/strdup16to8.c
new file mode 100644
index 0000000..1a8ba86
--- /dev/null
+++ b/package/utils/adbd/src/libcutils/strdup16to8.c
@@ -0,0 +1,168 @@
+/* libs/cutils/strdup16to8.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.
+*/
+
+#include <limits.h>  /* for SIZE_MAX */
+
+#include <cutils/jstring.h>
+#include <assert.h>
+#include <stdlib.h>
+
+
+/**
+ * Given a UTF-16 string, compute the length of the corresponding UTF-8
+ * string in bytes.
+ */
+extern size_t strnlen16to8(const char16_t* utf16Str, size_t len)
+{
+    size_t utf8Len = 0;
+
+    /* A small note on integer overflow. The result can
+     * potentially be as big as 3*len, which will overflow
+     * for len > SIZE_MAX/3.
+     *
+     * Moreover, the result of a strnlen16to8 is typically used
+     * to allocate a destination buffer to strncpy16to8 which
+     * requires one more byte to terminate the UTF-8 copy, and
+     * this is generally done by careless users by incrementing
+     * the result without checking for integer overflows, e.g.:
+     *
+     *   dst = malloc(strnlen16to8(utf16,len)+1)
+     *
+     * Due to this, the following code will try to detect
+     * overflows, and never return more than (SIZE_MAX-1)
+     * when it detects one. A careless user will try to malloc
+     * SIZE_MAX bytes, which will return NULL which can at least
+     * be detected appropriately.
+     *
+     * As far as I know, this function is only used by strndup16(),
+     * but better be safe than sorry.
+     */
+
+    /* Fast path for the usual case where 3*len is < SIZE_MAX-1.
+     */
+    if (len < (SIZE_MAX-1)/3) {
+        while (len--) {
+            unsigned int uic = *utf16Str++;
+
+            if (uic > 0x07ff)
+                utf8Len += 3;
+            else if (uic > 0x7f || uic == 0)
+                utf8Len += 2;
+            else
+                utf8Len++;
+        }
+        return utf8Len;
+    }
+
+    /* The slower but paranoid version */
+    while (len--) {
+        unsigned int  uic     = *utf16Str++;
+        size_t        utf8Cur = utf8Len;
+
+        if (uic > 0x07ff)
+            utf8Len += 3;
+        else if (uic > 0x7f || uic == 0)
+            utf8Len += 2;
+        else
+            utf8Len++;
+
+        if (utf8Len < utf8Cur) /* overflow detected */
+            return SIZE_MAX-1;
+    }
+
+    /* don't return SIZE_MAX to avoid common user bug */
+    if (utf8Len == SIZE_MAX)
+        utf8Len = SIZE_MAX-1;
+
+    return utf8Len;
+}
+
+
+/**
+ * Convert a Java-Style UTF-16 string + length to a JNI-Style UTF-8 string.
+ *
+ * This basically means: embedded \0's in the UTF-16 string are encoded
+ * as "0xc0 0x80"
+ *
+ * Make sure you allocate "utf8Str" with the result of strlen16to8() + 1,
+ * not just "len".
+ *
+ * Please note, a terminated \0 is always added, so your result will always
+ * be "strlen16to8() + 1" bytes long.
+ */
+extern char* strncpy16to8(char* utf8Str, const char16_t* utf16Str, size_t len)
+{
+    char* utf8cur = utf8Str;
+
+    /* Note on overflows: We assume the user did check the result of
+     * strnlen16to8() properly or at a minimum checked the result of
+     * its malloc(SIZE_MAX) in case of overflow.
+     */
+    while (len--) {
+        unsigned int uic = *utf16Str++;
+
+        if (uic > 0x07ff) {
+            *utf8cur++ = (uic >> 12) | 0xe0;
+            *utf8cur++ = ((uic >> 6) & 0x3f) | 0x80;
+            *utf8cur++ = (uic & 0x3f) | 0x80;
+        } else if (uic > 0x7f || uic == 0) {
+            *utf8cur++ = (uic >> 6) | 0xc0;
+            *utf8cur++ = (uic & 0x3f) | 0x80;
+        } else {
+            *utf8cur++ = uic;
+
+            if (uic == 0) {
+                break;
+            }
+        }
+    }
+
+   *utf8cur = '\0';
+
+   return utf8Str;
+}
+
+/**
+ * Convert a UTF-16 string to UTF-8.
+ *
+ */
+char * strndup16to8 (const char16_t* s, size_t n)
+{
+    char*   ret;
+    size_t  len;
+
+    if (s == NULL) {
+        return NULL;
+    }
+
+    len = strnlen16to8(s, n);
+
+    /* We are paranoid, and we check for SIZE_MAX-1
+     * too since it is an overflow value for our
+     * strnlen16to8 implementation.
+     */
+    if (len >= SIZE_MAX-1)
+        return NULL;
+
+    ret = malloc(len + 1);
+    if (ret == NULL)
+        return NULL;
+
+    strncpy16to8 (ret, s, n);
+
+    return ret;
+}
diff --git a/package/utils/adbd/src/libcutils/strdup8to16.c b/package/utils/adbd/src/libcutils/strdup8to16.c
new file mode 100644
index 0000000..63e5ca4
--- /dev/null
+++ b/package/utils/adbd/src/libcutils/strdup8to16.c
@@ -0,0 +1,214 @@
+/* libs/cutils/strdup8to16.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.
+*/
+
+#include <cutils/jstring.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <limits.h>
+
+/* See http://www.unicode.org/reports/tr22/ for discussion
+ * on invalid sequences
+ */
+
+#define UTF16_REPLACEMENT_CHAR 0xfffd
+
+/* Clever trick from Dianne that returns 1-4 depending on leading bit sequence*/
+#define UTF8_SEQ_LENGTH(ch) (((0xe5000000 >> ((ch >> 3) & 0x1e)) & 3) + 1)
+
+/* note: macro expands to multiple lines */
+#define UTF8_SHIFT_AND_MASK(unicode, byte)  \
+            (unicode)<<=6; (unicode) |= (0x3f & (byte));
+
+#define UNICODE_UPPER_LIMIT 0x10fffd    
+
+/**
+ * out_len is an out parameter (which may not be null) containing the
+ * length of the UTF-16 string (which may contain embedded \0's)
+ */
+
+extern char16_t * strdup8to16 (const char* s, size_t *out_len)
+{
+    char16_t *ret;
+    size_t len;
+
+    if (s == NULL) return NULL;
+
+    len = strlen8to16(s);
+
+    // fail on overflow
+    if (len && SIZE_MAX/len < sizeof(char16_t))
+        return NULL;
+
+    // no plus-one here. UTF-16 strings are not null terminated
+    ret = (char16_t *) malloc (sizeof(char16_t) * len);
+
+    return strcpy8to16 (ret, s, out_len);
+}
+
+/**
+ * Like "strlen", but for strings encoded with Java's modified UTF-8.
+ *
+ * The value returned is the number of UTF-16 characters required
+ * to represent this string.
+ */
+extern size_t strlen8to16 (const char* utf8Str)
+{
+    size_t len = 0;
+    int ic;
+    int expected = 0;
+
+    while ((ic = *utf8Str++) != '\0') {
+        /* bytes that start 0? or 11 are lead bytes and count as characters.*/
+        /* bytes that start 10 are extention bytes and are not counted */
+         
+        if ((ic & 0xc0) == 0x80) {
+            /* count the 0x80 extention bytes. if we have more than
+             * expected, then start counting them because strcpy8to16
+             * will insert UTF16_REPLACEMENT_CHAR's
+             */
+            expected--;
+            if (expected < 0) {
+                len++;
+            }
+        } else {
+            len++;
+            expected = UTF8_SEQ_LENGTH(ic) - 1;
+
+            /* this will result in a surrogate pair */
+            if (expected == 3) {
+                len++;
+            }
+        }
+    }
+
+    return len;
+}
+
+
+
+/*
+ * Retrieve the next UTF-32 character from a UTF-8 string.
+ *
+ * Stops at inner \0's
+ *
+ * Returns UTF16_REPLACEMENT_CHAR if an invalid sequence is encountered
+ *
+ * Advances "*pUtf8Ptr" to the start of the next character.
+ */
+static inline uint32_t getUtf32FromUtf8(const char** pUtf8Ptr)
+{
+    uint32_t ret;
+    int seq_len;
+    int i;
+
+    /* Mask for leader byte for lengths 1, 2, 3, and 4 respectively*/
+    static const char leaderMask[4] = {0xff, 0x1f, 0x0f, 0x07};
+
+    /* Bytes that start with bits "10" are not leading characters. */
+    if (((**pUtf8Ptr) & 0xc0) == 0x80) {
+        (*pUtf8Ptr)++;
+        return UTF16_REPLACEMENT_CHAR;
+    }
+
+    /* note we tolerate invalid leader 11111xxx here */    
+    seq_len = UTF8_SEQ_LENGTH(**pUtf8Ptr);
+
+    ret = (**pUtf8Ptr) & leaderMask [seq_len - 1];
+
+    if (**pUtf8Ptr == '\0') return ret;
+
+    (*pUtf8Ptr)++;
+    for (i = 1; i < seq_len ; i++, (*pUtf8Ptr)++) {
+        if ((**pUtf8Ptr) == '\0') return UTF16_REPLACEMENT_CHAR;
+        if (((**pUtf8Ptr) & 0xc0) != 0x80) return UTF16_REPLACEMENT_CHAR;
+
+        UTF8_SHIFT_AND_MASK(ret, **pUtf8Ptr);
+    }
+
+    return ret;
+}
+
+
+/**
+ * out_len is an out parameter (which may not be null) containing the
+ * length of the UTF-16 string (which may contain embedded \0's)
+ */
+
+extern char16_t * strcpy8to16 (char16_t *utf16Str, const char*utf8Str, 
+                                       size_t *out_len)
+{   
+    char16_t *dest = utf16Str;
+
+    while (*utf8Str != '\0') {
+        uint32_t ret;
+
+        ret = getUtf32FromUtf8(&utf8Str);
+
+        if (ret <= 0xffff) {
+            *dest++ = (char16_t) ret;
+        } else if (ret <= UNICODE_UPPER_LIMIT)  {
+            /* Create surrogate pairs */
+            /* See http://en.wikipedia.org/wiki/UTF-16/UCS-2#Method_for_code_points_in_Plane_1.2C_Plane_2 */
+
+            *dest++ = 0xd800 | ((ret - 0x10000) >> 10);
+            *dest++ = 0xdc00 | ((ret - 0x10000) &  0x3ff);
+        } else {
+            *dest++ = UTF16_REPLACEMENT_CHAR;
+        }
+    }
+
+    *out_len = dest - utf16Str;
+
+    return utf16Str;
+}
+
+/**
+ * length is the number of characters in the UTF-8 string.
+ * out_len is an out parameter (which may not be null) containing the
+ * length of the UTF-16 string (which may contain embedded \0's)
+ */
+
+extern char16_t * strcpylen8to16 (char16_t *utf16Str, const char*utf8Str,
+                                       int length, size_t *out_len)
+{
+    /* TODO: Share more of this code with the method above. Only 2 lines changed. */
+    
+    char16_t *dest = utf16Str;
+
+    const char *end = utf8Str + length; /* This line */
+    while (utf8Str < end) {             /* and this line changed. */
+        uint32_t ret;
+
+        ret = getUtf32FromUtf8(&utf8Str);
+
+        if (ret <= 0xffff) {
+            *dest++ = (char16_t) ret;
+        } else if (ret <= UNICODE_UPPER_LIMIT)  {
+            /* Create surrogate pairs */
+            /* See http://en.wikipedia.org/wiki/UTF-16/UCS-2#Method_for_code_points_in_Plane_1.2C_Plane_2 */
+
+            *dest++ = 0xd800 | ((ret - 0x10000) >> 10);
+            *dest++ = 0xdc00 | ((ret - 0x10000) &  0x3ff);
+        } else {
+            *dest++ = UTF16_REPLACEMENT_CHAR;
+        }
+    }
+
+    *out_len = dest - utf16Str;
+
+    return utf16Str;
+}
diff --git a/package/utils/adbd/src/libcutils/tests/Android.mk b/package/utils/adbd/src/libcutils/tests/Android.mk
new file mode 100644
index 0000000..8e65310
--- /dev/null
+++ b/package/utils/adbd/src/libcutils/tests/Android.mk
@@ -0,0 +1,48 @@
+# Copyright (C) 2014 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.
+
+LOCAL_PATH := $(call my-dir)
+
+test_src_files := \
+    MemsetTest.cpp \
+    PropertiesTest.cpp \
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libcutils_test
+LOCAL_SRC_FILES := $(test_src_files)
+LOCAL_SHARED_LIBRARIES := \
+    libcutils \
+    liblog \
+    libutils \
+
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+include $(BUILD_NATIVE_TEST)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libcutils_test_static
+LOCAL_FORCE_STATIC_EXECUTABLE := true
+LOCAL_SRC_FILES := $(test_src_files)
+LOCAL_STATIC_LIBRARIES := \
+    libc \
+    libcutils \
+    liblog \
+    libstlport_static \
+    libutils \
+
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+include $(BUILD_NATIVE_TEST)
diff --git a/package/utils/adbd/src/libcutils/tests/MemsetTest.cpp b/package/utils/adbd/src/libcutils/tests/MemsetTest.cpp
new file mode 100644
index 0000000..45efc51
--- /dev/null
+++ b/package/utils/adbd/src/libcutils/tests/MemsetTest.cpp
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2014 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 <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+
+#include <cutils/memory.h>
+#include <gtest/gtest.h>
+
+#define FENCEPOST_LENGTH 8
+
+#define MAX_TEST_SIZE (64*1024)
+// Choose values that have no repeating byte values.
+#define MEMSET16_PATTERN 0xb139
+#define MEMSET32_PATTERN 0x48193a27
+
+enum test_e {
+  MEMSET16 = 0,
+  MEMSET32,
+};
+
+static int g_memset16_aligns[][2] = {
+  { 2, 0 },
+  { 4, 0 },
+  { 8, 0 },
+  { 16, 0 },
+  { 32, 0 },
+  { 64, 0 },
+  { 128, 0 },
+
+  { 4, 2 },
+
+  { 8, 2 },
+  { 8, 4 },
+  { 8, 6 },
+
+  { 128, 2 },
+  { 128, 4 },
+  { 128, 6 },
+  { 128, 8 },
+  { 128, 10 },
+  { 128, 12 },
+  { 128, 14 },
+  { 128, 16 },
+};
+
+static int g_memset32_aligns[][2] = {
+  { 4, 0 },
+  { 8, 0 },
+  { 16, 0 },
+  { 32, 0 },
+  { 64, 0 },
+  { 128, 0 },
+
+  { 8, 4 },
+
+  { 128, 4 },
+  { 128, 8 },
+  { 128, 12 },
+  { 128, 16 },
+};
+
+static size_t GetIncrement(size_t len, size_t min_incr) {
+  if (len >= 4096) {
+    return 1024;
+  } else if (len >= 1024) {
+    return 256;
+  }
+  return min_incr;
+}
+
+// Return a pointer into the current buffer with the specified alignment.
+static void *GetAlignedPtr(void *orig_ptr, int alignment, int or_mask) {
+  uint64_t ptr = reinterpret_cast<uint64_t>(orig_ptr);
+  if (alignment > 0) {
+      // When setting the alignment, set it to exactly the alignment chosen.
+      // The pointer returned will be guaranteed not to be aligned to anything
+      // more than that.
+      ptr += alignment - (ptr & (alignment - 1));
+      ptr |= alignment | or_mask;
+  }
+
+  return reinterpret_cast<void*>(ptr);
+}
+
+static void SetFencepost(uint8_t *buffer) {
+  for (int i = 0; i < FENCEPOST_LENGTH; i += 2) {
+    buffer[i] = 0xde;
+    buffer[i+1] = 0xad;
+  }
+}
+
+static void VerifyFencepost(uint8_t *buffer) {
+  for (int i = 0; i < FENCEPOST_LENGTH; i += 2) {
+    if (buffer[i] != 0xde || buffer[i+1] != 0xad) {
+      uint8_t expected_value;
+      if (buffer[i] == 0xde) {
+        i++;
+        expected_value = 0xad;
+      } else {
+        expected_value = 0xde;
+      }
+      ASSERT_EQ(expected_value, buffer[i]);
+    }
+  }
+}
+
+void RunMemsetTests(test_e test_type, uint32_t value, int align[][2], size_t num_aligns) {
+  size_t min_incr = 4;
+  if (test_type == MEMSET16) {
+    min_incr = 2;
+    value |= value << 16;
+  }
+  uint32_t* expected_buf = new uint32_t[MAX_TEST_SIZE/sizeof(uint32_t)];
+  for (size_t i = 0; i < MAX_TEST_SIZE/sizeof(uint32_t); i++) {
+    expected_buf[i] = value;
+  }
+
+  // Allocate one large buffer with lots of extra space so that we can
+  // guarantee that all possible alignments will fit.
+  uint8_t *buf = new uint8_t[3*MAX_TEST_SIZE];
+  uint8_t *buf_align;
+  for (size_t i = 0; i < num_aligns; i++) {
+    size_t incr = min_incr;
+    for (size_t len = incr; len <= MAX_TEST_SIZE; len += incr) {
+      incr = GetIncrement(len, min_incr);
+
+      buf_align = reinterpret_cast<uint8_t*>(GetAlignedPtr(
+          buf+FENCEPOST_LENGTH, align[i][0], align[i][1]));
+
+      SetFencepost(&buf_align[-FENCEPOST_LENGTH]);
+      SetFencepost(&buf_align[len]);
+
+      memset(buf_align, 0xff, len);
+      if (test_type == MEMSET16) {
+        android_memset16(reinterpret_cast<uint16_t*>(buf_align), value, len);
+      } else {
+        android_memset32(reinterpret_cast<uint32_t*>(buf_align), value, len);
+      }
+      ASSERT_EQ(0, memcmp(expected_buf, buf_align, len))
+          << "Failed size " << len << " align " << align[i][0] << " " << align[i][1] << "\n";
+
+      VerifyFencepost(&buf_align[-FENCEPOST_LENGTH]);
+      VerifyFencepost(&buf_align[len]);
+    }
+  }
+  delete expected_buf;
+  delete buf;
+}
+
+TEST(libcutils, android_memset16_non_zero) {
+  RunMemsetTests(MEMSET16, MEMSET16_PATTERN, g_memset16_aligns, sizeof(g_memset16_aligns)/sizeof(int[2]));
+}
+
+TEST(libcutils, android_memset16_zero) {
+  RunMemsetTests(MEMSET16, 0, g_memset16_aligns, sizeof(g_memset16_aligns)/sizeof(int[2]));
+}
+
+TEST(libcutils, android_memset32_non_zero) {
+  RunMemsetTests(MEMSET32, MEMSET32_PATTERN, g_memset32_aligns, sizeof(g_memset32_aligns)/sizeof(int[2]));
+}
+
+TEST(libcutils, android_memset32_zero) {
+  RunMemsetTests(MEMSET32, 0, g_memset32_aligns, sizeof(g_memset32_aligns)/sizeof(int[2]));
+}
diff --git a/package/utils/adbd/src/libcutils/tests/PropertiesTest.cpp b/package/utils/adbd/src/libcutils/tests/PropertiesTest.cpp
new file mode 100644
index 0000000..659821c
--- /dev/null
+++ b/package/utils/adbd/src/libcutils/tests/PropertiesTest.cpp
@@ -0,0 +1,309 @@
+/*
+ * Copyright (C) 2014 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 LOG_TAG "Properties_test"
+#include <utils/Log.h>
+#include <gtest/gtest.h>
+
+#include <cutils/properties.h>
+#include <limits.h>
+#include <string>
+#include <sstream>
+#include <iostream>
+
+namespace android {
+
+#define STRINGIFY_INNER(x) #x
+#define STRINGIFY(x) STRINGIFY_INNER(x)
+#define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
+#define ASSERT_OK(x) ASSERT_EQ(0, (x))
+#define EXPECT_OK(x) EXPECT_EQ(0, (x))
+
+#define PROPERTY_TEST_KEY "libcutils.test.key"
+#define PROPERTY_TEST_VALUE_DEFAULT "<<<default_value>>>"
+
+template <typename T>
+static std::string HexString(T value) {
+    std::stringstream ss;
+    ss << "0x" << std::hex << std::uppercase << value;
+    return ss.str();
+}
+
+template <typename T>
+static ::testing::AssertionResult AssertEqualHex(const char *mExpr,
+        const char *nExpr,
+        T m,
+        T n) {
+    if (m == n) {
+        return ::testing::AssertionSuccess();
+    }
+
+    return ::testing::AssertionFailure()
+        << mExpr << " and " << nExpr << " (expected: " << HexString(m) <<
+        ", actual: " << HexString(n) << ") are not equal";
+}
+
+class PropertiesTest : public testing::Test {
+public:
+    PropertiesTest() : mValue() {}
+protected:
+    virtual void SetUp() {
+        EXPECT_OK(property_set(PROPERTY_TEST_KEY, /*value*/NULL));
+    }
+
+    virtual void TearDown() {
+        EXPECT_OK(property_set(PROPERTY_TEST_KEY, /*value*/NULL));
+    }
+
+    char mValue[PROPERTY_VALUE_MAX];
+
+    template <typename T>
+    static std::string ToString(T value) {
+        std::stringstream ss;
+        ss << value;
+
+        return ss.str();
+    }
+
+    // Return length of property read; value is written into mValue
+    int SetAndGetProperty(const char* value, const char* defaultValue = PROPERTY_TEST_VALUE_DEFAULT) {
+        EXPECT_OK(property_set(PROPERTY_TEST_KEY, value)) << "value: '" << value << "'";
+        return property_get(PROPERTY_TEST_KEY, mValue, defaultValue);
+    }
+
+    void ResetValue(unsigned char c = 0xFF) {
+        for (size_t i = 0; i < ARRAY_SIZE(mValue); ++i) {
+            mValue[i] = (char) c;
+        }
+    }
+};
+
+TEST_F(PropertiesTest, SetString) {
+
+    // Null key -> unsuccessful set
+    {
+        // Null key -> fails
+        EXPECT_GT(0, property_set(/*key*/NULL, PROPERTY_TEST_VALUE_DEFAULT));
+    }
+
+    // Null value -> returns default value
+    {
+        // Null value -> OK , and it clears the value
+        EXPECT_OK(property_set(PROPERTY_TEST_KEY, /*value*/NULL));
+        ResetValue();
+
+        // Since the value is null, default value will be returned
+        int len = property_get(PROPERTY_TEST_KEY, mValue, PROPERTY_TEST_VALUE_DEFAULT);
+        EXPECT_EQ(strlen(PROPERTY_TEST_VALUE_DEFAULT), len);
+        EXPECT_STREQ(PROPERTY_TEST_VALUE_DEFAULT, mValue);
+    }
+
+    // Trivial case => get returns what was set
+    {
+        int len = SetAndGetProperty("hello_world");
+        EXPECT_EQ(strlen("hello_world"), len) << "hello_world key";
+        EXPECT_STREQ("hello_world", mValue);
+        ResetValue();
+    }
+
+    // Set to empty string => get returns default always
+    {
+        const char* EMPTY_STRING_DEFAULT = "EMPTY_STRING";
+        int len = SetAndGetProperty("", EMPTY_STRING_DEFAULT);
+        EXPECT_EQ(strlen(EMPTY_STRING_DEFAULT), len) << "empty key";
+        EXPECT_STREQ(EMPTY_STRING_DEFAULT, mValue);
+        ResetValue();
+    }
+
+    // Set to max length => get returns what was set
+    {
+        std::string maxLengthString = std::string(PROPERTY_VALUE_MAX-1, 'a');
+
+        int len = SetAndGetProperty(maxLengthString.c_str());
+        EXPECT_EQ(PROPERTY_VALUE_MAX-1, len) << "max length key";
+        EXPECT_STREQ(maxLengthString.c_str(), mValue);
+        ResetValue();
+    }
+
+    // Set to max length + 1 => set fails
+    {
+        const char* VALID_TEST_VALUE = "VALID_VALUE";
+        ASSERT_OK(property_set(PROPERTY_TEST_KEY, VALID_TEST_VALUE));
+
+        std::string oneLongerString = std::string(PROPERTY_VALUE_MAX, 'a');
+
+        // Expect that the value set fails since it's too long
+        EXPECT_GT(0, property_set(PROPERTY_TEST_KEY, oneLongerString.c_str()));
+        int len = property_get(PROPERTY_TEST_KEY, mValue, PROPERTY_TEST_VALUE_DEFAULT);
+
+        EXPECT_EQ(strlen(VALID_TEST_VALUE), len) << "set should've failed";
+        EXPECT_STREQ(VALID_TEST_VALUE, mValue);
+        ResetValue();
+    }
+}
+
+TEST_F(PropertiesTest, GetString) {
+
+    // Try to use a default value that's too long => set fails
+    {
+        ASSERT_OK(property_set(PROPERTY_TEST_KEY, ""));
+
+        std::string maxLengthString = std::string(PROPERTY_VALUE_MAX-1, 'a');
+        std::string oneLongerString = std::string(PROPERTY_VALUE_MAX, 'a');
+
+        // Expect that the value is truncated since it's too long (by 1)
+        int len = property_get(PROPERTY_TEST_KEY, mValue, oneLongerString.c_str());
+        EXPECT_EQ(PROPERTY_VALUE_MAX-1, len);
+        EXPECT_STREQ(maxLengthString.c_str(), mValue);
+        ResetValue();
+    }
+}
+
+TEST_F(PropertiesTest, GetBool) {
+    /**
+     * TRUE
+     */
+    const char *valuesTrue[] = { "1", "true", "y", "yes", "on", };
+    for (size_t i = 0; i < ARRAY_SIZE(valuesTrue); ++i) {
+        ASSERT_OK(property_set(PROPERTY_TEST_KEY, valuesTrue[i]));
+        bool val = property_get_bool(PROPERTY_TEST_KEY, /*default_value*/false);
+        EXPECT_TRUE(val) << "Property should've been TRUE for value: '" << valuesTrue[i] << "'";
+    }
+
+    /**
+     * FALSE
+     */
+    const char *valuesFalse[] = { "0", "false", "n", "no", "off", };
+    for (size_t i = 0; i < ARRAY_SIZE(valuesFalse); ++i) {
+        ASSERT_OK(property_set(PROPERTY_TEST_KEY, valuesFalse[i]));
+        bool val = property_get_bool(PROPERTY_TEST_KEY, /*default_value*/true);
+        EXPECT_FALSE(val) << "Property shoud've been FALSE For string value: '" << valuesFalse[i] << "'";
+    }
+
+    /**
+     * NEITHER
+     */
+    const char *valuesNeither[] = { "x0", "x1", "2", "-2", "True", "False", "garbage", "", " ",
+            "+1", "  1  ", "  true", "  true  ", "  y  ", "  yes", "yes  ",
+            "+0", "-0", "00", "  00  ", "  false", "false  ",
+    };
+    for (size_t i = 0; i < ARRAY_SIZE(valuesNeither); ++i) {
+        ASSERT_OK(property_set(PROPERTY_TEST_KEY, valuesNeither[i]));
+
+        // The default value should always be used
+        bool val = property_get_bool(PROPERTY_TEST_KEY, /*default_value*/true);
+        EXPECT_TRUE(val) << "Property should've been NEITHER (true) for string value: '" << valuesNeither[i] << "'";
+
+        val = property_get_bool(PROPERTY_TEST_KEY, /*default_value*/false);
+        EXPECT_FALSE(val) << "Property should've been NEITHER (false) for string value: '" << valuesNeither[i] << "'";
+    }
+}
+
+TEST_F(PropertiesTest, GetInt64) {
+    const int64_t DEFAULT_VALUE = INT64_C(0xDEADBEEFBEEFDEAD);
+
+    const std::string longMaxString = ToString(INT64_MAX);
+    const std::string longStringOverflow = longMaxString + "0";
+
+    const std::string longMinString = ToString(INT64_MIN);
+    const std::string longStringUnderflow = longMinString + "0";
+
+    const char* setValues[] = {
+        // base 10
+        "1", "2", "12345", "-1", "-2", "-12345",
+        // base 16
+        "0xFF", "0x0FF", "0xC0FFEE",
+        // base 8
+        "0", "01234", "07",
+        // corner cases
+        "       2", "2      ", "+0", "-0", "  +0   ", longMaxString.c_str(), longMinString.c_str(),
+        // failing cases
+        NULL, "", " ", "    ", "hello", "     true     ", "y",
+        longStringOverflow.c_str(), longStringUnderflow.c_str(),
+    };
+
+    int64_t getValues[] = {
+        // base 10
+        1, 2, 12345, -1, -2, -12345,
+        // base 16
+        0xFF, 0x0FF, 0xC0FFEE,
+        // base 8
+        0, 01234, 07,
+        // corner cases
+        2, 2, 0, 0, 0, INT64_MAX, INT64_MIN,
+        // failing cases
+        DEFAULT_VALUE, DEFAULT_VALUE, DEFAULT_VALUE, DEFAULT_VALUE, DEFAULT_VALUE, DEFAULT_VALUE, DEFAULT_VALUE,
+        DEFAULT_VALUE, DEFAULT_VALUE,
+    };
+
+    ASSERT_EQ(ARRAY_SIZE(setValues), ARRAY_SIZE(getValues));
+
+    for (size_t i = 0; i < ARRAY_SIZE(setValues); ++i) {
+        ASSERT_OK(property_set(PROPERTY_TEST_KEY, setValues[i]));
+
+        int64_t val = property_get_int64(PROPERTY_TEST_KEY, DEFAULT_VALUE);
+        EXPECT_PRED_FORMAT2(AssertEqualHex, getValues[i], val) << "Property was set to '" << setValues[i] << "'";
+    }
+}
+
+TEST_F(PropertiesTest, GetInt32) {
+    const int32_t DEFAULT_VALUE = INT32_C(0xDEADBEEF);
+
+    const std::string intMaxString = ToString(INT32_MAX);
+    const std::string intStringOverflow = intMaxString + "0";
+
+    const std::string intMinString = ToString(INT32_MIN);
+    const std::string intStringUnderflow = intMinString + "0";
+
+    const char* setValues[] = {
+        // base 10
+        "1", "2", "12345", "-1", "-2", "-12345",
+        // base 16
+        "0xFF", "0x0FF", "0xC0FFEE", "0Xf00",
+        // base 8
+        "0", "01234", "07",
+        // corner cases
+        "       2", "2      ", "+0", "-0", "  +0   ", intMaxString.c_str(), intMinString.c_str(),
+        // failing cases
+        NULL, "", " ", "    ", "hello", "     true     ", "y",
+        intStringOverflow.c_str(), intStringUnderflow.c_str(),
+    };
+
+    int32_t getValues[] = {
+        // base 10
+        1, 2, 12345, -1, -2, -12345,
+        // base 16
+        0xFF, 0x0FF, 0xC0FFEE, 0Xf00,
+        // base 8
+        0, 01234, 07,
+        // corner cases
+        2, 2, 0, 0, 0, INT32_MAX, INT32_MIN,
+        // failing cases
+        DEFAULT_VALUE, DEFAULT_VALUE, DEFAULT_VALUE, DEFAULT_VALUE, DEFAULT_VALUE, DEFAULT_VALUE, DEFAULT_VALUE,
+        DEFAULT_VALUE, DEFAULT_VALUE,
+    };
+
+    ASSERT_EQ(ARRAY_SIZE(setValues), ARRAY_SIZE(getValues));
+
+    for (size_t i = 0; i < ARRAY_SIZE(setValues); ++i) {
+        ASSERT_OK(property_set(PROPERTY_TEST_KEY, setValues[i]));
+
+        int32_t val = property_get_int32(PROPERTY_TEST_KEY, DEFAULT_VALUE);
+        EXPECT_PRED_FORMAT2(AssertEqualHex, getValues[i], val) << "Property was set to '" << setValues[i] << "'";
+    }
+}
+
+} // namespace android
diff --git a/package/utils/adbd/src/libcutils/threads.c b/package/utils/adbd/src/libcutils/threads.c
new file mode 100644
index 0000000..bf182f0
--- /dev/null
+++ b/package/utils/adbd/src/libcutils/threads.c
@@ -0,0 +1,82 @@
+/*
+** 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 <cutils/threads.h>
+
+#ifdef HAVE_PTHREADS
+void*  thread_store_get( thread_store_t*  store )
+{
+    if (!store->has_tls)
+        return NULL;
+
+    return pthread_getspecific( store->tls );
+}
+    
+extern void   thread_store_set( thread_store_t*          store, 
+                                void*                    value,
+                                thread_store_destruct_t  destroy)
+{
+    pthread_mutex_lock( &store->lock );
+    if (!store->has_tls) {
+        if (pthread_key_create( &store->tls, destroy) != 0) {
+            pthread_mutex_unlock(&store->lock);
+            return;
+        }
+        store->has_tls = 1;
+    }
+    pthread_mutex_unlock( &store->lock );
+
+    pthread_setspecific( store->tls, value );
+}
+
+#endif
+
+#ifdef HAVE_WIN32_THREADS
+void*  thread_store_get( thread_store_t*  store )
+{
+    if (!store->has_tls)
+        return NULL;
+    
+    return (void*) TlsGetValue( store->tls );
+}
+
+void   thread_store_set( thread_store_t*          store,
+                         void*                    value,
+                         thread_store_destruct_t  destroy )
+{
+    /* XXX: can't use destructor on thread exit */
+    if (!store->lock_init) {
+        store->lock_init = -1;
+        InitializeCriticalSection( &store->lock );
+        store->lock_init = -2;
+    } else while (store->lock_init != -2) {
+        Sleep(10); /* 10ms */
+    }
+        
+    EnterCriticalSection( &store->lock );
+    if (!store->has_tls) {
+        store->tls = TlsAlloc();
+        if (store->tls == TLS_OUT_OF_INDEXES) {
+            LeaveCriticalSection( &store->lock );
+            return;
+        }
+        store->has_tls = 1;
+    }
+    LeaveCriticalSection( &store->lock );
+    
+    TlsSetValue( store->tls, value );
+}
+#endif
diff --git a/package/utils/adbd/src/libcutils/trace.c b/package/utils/adbd/src/libcutils/trace.c
new file mode 100644
index 0000000..f57aac2
--- /dev/null
+++ b/package/utils/adbd/src/libcutils/trace.c
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2012 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 <limits.h>
+#include <pthread.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <cutils/atomic.h>
+#include <cutils/compiler.h>
+#include <cutils/properties.h>
+#include <cutils/trace.h>
+
+#define LOG_TAG "cutils-trace"
+#include <log/log.h>
+
+volatile int32_t        atrace_is_ready      = 0;
+int                     atrace_marker_fd     = -1;
+uint64_t                atrace_enabled_tags  = ATRACE_TAG_NOT_READY;
+static bool             atrace_is_debuggable = false;
+static volatile int32_t atrace_is_enabled    = 1;
+static pthread_once_t   atrace_once_control  = PTHREAD_ONCE_INIT;
+static pthread_mutex_t  atrace_tags_mutex    = PTHREAD_MUTEX_INITIALIZER;
+
+// Set whether this process is debuggable, which determines whether
+// application-level tracing is allowed when the ro.debuggable system property
+// is not set to '1'.
+void atrace_set_debuggable(bool debuggable)
+{
+    atrace_is_debuggable = debuggable;
+    atrace_update_tags();
+}
+
+// Set whether tracing is enabled in this process.  This is used to prevent
+// the Zygote process from tracing.
+void atrace_set_tracing_enabled(bool enabled)
+{
+    android_atomic_release_store(enabled ? 1 : 0, &atrace_is_enabled);
+    atrace_update_tags();
+}
+
+// Check whether the given command line matches one of the comma-separated
+// values listed in the app_cmdlines property.
+static bool atrace_is_cmdline_match(const char* cmdline)
+{
+    char value[PROPERTY_VALUE_MAX];
+    char* start = value;
+
+    property_get("debug.atrace.app_cmdlines", value, "");
+
+    while (start != NULL) {
+        char* end = strchr(start, ',');
+
+        if (end != NULL) {
+            *end = '\0';
+            end++;
+        }
+
+        if (strcmp(cmdline, start) == 0) {
+            return true;
+        }
+
+        start = end;
+    }
+
+    return false;
+}
+
+// Determine whether application-level tracing is enabled for this process.
+static bool atrace_is_app_tracing_enabled()
+{
+    bool sys_debuggable = false;
+    char value[PROPERTY_VALUE_MAX];
+    bool result = false;
+
+    // Check whether the system is debuggable.
+    property_get("ro.debuggable", value, "0");
+    if (value[0] == '1') {
+        sys_debuggable = true;
+    }
+
+    if (sys_debuggable || atrace_is_debuggable) {
+        // Check whether tracing is enabled for this process.
+        FILE * file = fopen("/proc/self/cmdline", "r");
+        if (file) {
+            char cmdline[4096];
+            if (fgets(cmdline, sizeof(cmdline), file)) {
+                result = atrace_is_cmdline_match(cmdline);
+            } else {
+                ALOGE("Error reading cmdline: %s (%d)", strerror(errno), errno);
+            }
+            fclose(file);
+        } else {
+            ALOGE("Error opening /proc/self/cmdline: %s (%d)", strerror(errno),
+                    errno);
+        }
+    }
+
+    return result;
+}
+
+// Read the sysprop and return the value tags should be set to
+static uint64_t atrace_get_property()
+{
+    char value[PROPERTY_VALUE_MAX];
+    char *endptr;
+    uint64_t tags;
+
+    property_get("debug.atrace.tags.enableflags", value, "0");
+    errno = 0;
+    tags = strtoull(value, &endptr, 0);
+    if (value[0] == '\0' || *endptr != '\0') {
+        ALOGE("Error parsing trace property: Not a number: %s", value);
+        return 0;
+    } else if (errno == ERANGE || tags == ULLONG_MAX) {
+        ALOGE("Error parsing trace property: Number too large: %s", value);
+        return 0;
+    }
+
+    // Only set the "app" tag if this process was selected for app-level debug
+    // tracing.
+    if (atrace_is_app_tracing_enabled()) {
+        tags |= ATRACE_TAG_APP;
+    } else {
+        tags &= ~ATRACE_TAG_APP;
+    }
+
+    return (tags | ATRACE_TAG_ALWAYS) & ATRACE_TAG_VALID_MASK;
+}
+
+// Update tags if tracing is ready. Useful as a sysprop change callback.
+void atrace_update_tags()
+{
+    uint64_t tags;
+    if (CC_UNLIKELY(android_atomic_acquire_load(&atrace_is_ready))) {
+        if (android_atomic_acquire_load(&atrace_is_enabled)) {
+            tags = atrace_get_property();
+            pthread_mutex_lock(&atrace_tags_mutex);
+            atrace_enabled_tags = tags;
+            pthread_mutex_unlock(&atrace_tags_mutex);
+        } else {
+            // Tracing is disabled for this process, so we simply don't
+            // initialize the tags.
+            pthread_mutex_lock(&atrace_tags_mutex);
+            atrace_enabled_tags = ATRACE_TAG_NOT_READY;
+            pthread_mutex_unlock(&atrace_tags_mutex);
+        }
+    }
+}
+
+static void atrace_init_once()
+{
+    atrace_marker_fd = open("/sys/kernel/debug/tracing/trace_marker", O_WRONLY);
+    if (atrace_marker_fd == -1) {
+        ALOGE("Error opening trace file: %s (%d)", strerror(errno), errno);
+        atrace_enabled_tags = 0;
+        goto done;
+    }
+
+    atrace_enabled_tags = atrace_get_property();
+
+done:
+    android_atomic_release_store(1, &atrace_is_ready);
+}
+
+void atrace_setup()
+{
+    pthread_once(&atrace_once_control, atrace_init_once);
+}
diff --git a/package/utils/adbd/src/libcutils/uevent.c b/package/utils/adbd/src/libcutils/uevent.c
new file mode 100644
index 0000000..97a81e3
--- /dev/null
+++ b/package/utils/adbd/src/libcutils/uevent.c
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2011 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 <cutils/uevent.h>
+
+#include <errno.h>
+#include <stdbool.h>
+#include <string.h>
+#include <strings.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#include <linux/netlink.h>
+
+/**
+ * Like recv(), but checks that messages actually originate from the kernel.
+ */
+ssize_t uevent_kernel_multicast_recv(int socket, void *buffer, size_t length)
+{
+    uid_t user = -1;
+    return uevent_kernel_multicast_uid_recv(socket, buffer, length, &user);
+}
+
+/**
+ * Like the above, but passes a uid_t in by reference. In the event that this
+ * fails due to a bad uid check, the uid_t will be set to the uid of the
+ * socket's peer.
+ *
+ * If this method rejects a netlink message from outside the kernel, it
+ * returns -1, sets errno to EIO, and sets "user" to the UID associated with the
+ * message. If the peer UID cannot be determined, "user" is set to -1."
+ */
+ssize_t uevent_kernel_multicast_uid_recv(int socket, void *buffer,
+                                         size_t length, uid_t *user)
+{
+    struct iovec iov = { buffer, length };
+    struct sockaddr_nl addr;
+    char control[CMSG_SPACE(sizeof(struct ucred))];
+    struct msghdr hdr = {
+        &addr,
+        sizeof(addr),
+        &iov,
+        1,
+        control,
+        sizeof(control),
+        0,
+    };
+
+    *user = -1;
+    ssize_t n = recvmsg(socket, &hdr, 0);
+    if (n <= 0) {
+        return n;
+    }
+
+    struct cmsghdr *cmsg = CMSG_FIRSTHDR(&hdr);
+    if (cmsg == NULL || cmsg->cmsg_type != SCM_CREDENTIALS) {
+        /* ignoring netlink message with no sender credentials */
+        goto out;
+    }
+
+    struct ucred *cred = (struct ucred *)CMSG_DATA(cmsg);
+    *user = cred->uid;
+    if (cred->uid != 0) {
+        /* ignoring netlink message from non-root user */
+        goto out;
+    }
+
+    if (addr.nl_groups == 0 || addr.nl_pid != 0) {
+        /* ignoring non-kernel or unicast netlink message */
+        goto out;
+    }
+
+    return n;
+
+out:
+    /* clear residual potentially malicious data */
+    bzero(buffer, length);
+    errno = EIO;
+    return -1;
+}
+
+int uevent_open_socket(int buf_sz, bool passcred)
+{
+    struct sockaddr_nl addr;
+    int on = passcred;
+    int s;
+
+    memset(&addr, 0, sizeof(addr));
+    addr.nl_family = AF_NETLINK;
+    addr.nl_pid = getpid();
+    addr.nl_groups = 0xffffffff;
+
+    s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
+    if(s < 0)
+        return -1;
+
+    setsockopt(s, SOL_SOCKET, SO_RCVBUFFORCE, &buf_sz, sizeof(buf_sz));
+    setsockopt(s, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on));
+
+    if(bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+        close(s);
+        return -1;
+    }
+
+    return s;
+}
diff --git a/package/utils/audit/Makefile b/package/utils/audit/Makefile
new file mode 100644
index 0000000..48ec8d7
--- /dev/null
+++ b/package/utils/audit/Makefile
@@ -0,0 +1,187 @@
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=audit-userspace
+PKG_VERSION:=3.1.5
+PKG_RELEASE:=1
+
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_URL:=https://github.com/linux-audit/$(PKG_NAME).git
+PKG_SOURCE_VERSION:=v$(PKG_VERSION)
+PKG_MIRROR_HASH:=1e00ac07679ba5801732a2b3ec4f6fcbd0c31901cbffbc2cab14f0953e5b2030
+
+PKG_MAINTAINER:=Thomas Petazzoni <thomas.petazzoni@bootlin.com>
+PKG_LICENSE:=GPL-2.0-or-later LGPL-2.1-or-later
+PKG_LICENSE_FILES:=COPYING COPYING.LIB
+PKG_CPE_ID:=cpe:/a:linux_audit_project:linux_audit
+
+PKG_CONFIG_DEPENDS:=CONFIG_KERNEL_IO_URING
+PKG_FIXUP:=autoreconf
+
+PKG_BUILD_FLAGS:=no-mips16
+PKG_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/host-build.mk
+
+define Package/audit/Default
+  TITLE:=Audit
+  URL:=https://github.com/linux-audit/
+endef
+
+define Package/audit/Default/description
+  The audit package contains the user space utilities for
+  storing and searching the audit records generated by
+  the audit subsystem in the kernel.
+endef
+
+define Package/libaudit
+$(call Package/audit/Default)
+  SECTION:=libs
+  CATEGORY:=Libraries
+  TITLE+= (libaudit)
+endef
+
+define Package/libaudit/description
+$(call Package/audit/Default/description)
+  This package contains the audit shared library.
+endef
+
+define Package/libauparse
+$(call Package/audit/Default)
+  SECTION:=libs
+  CATEGORY:=Libraries
+  TITLE+= (libauparse)
+  DEPENDS:= +libaudit
+endef
+
+define Package/libauparse/description
+$(call Package/audit/Default/description)
+  This package contains the audit parsing shared library.
+endef
+
+define Package/audit-utils
+$(call Package/audit/Default)
+  SECTION:=admin
+  CATEGORY:=Administration
+  TITLE+= (utilities)
+  DEPENDS:= +libaudit +libauparse
+endef
+
+define Package/audit-utils/description
+$(call Package/audit/Default/description)
+  This package contains the audit utilities.
+endef
+
+define Package/auditd
+$(call Package/audit/Default)
+  SECTION:=admin
+  CATEGORY:=Administration
+  TITLE+= (daemon)
+  DEPENDS:= +libaudit +libauparse +audit-utils +libev
+endef
+
+define Package/auditd/description
+$(call Package/audit/Default/description)
+  This package contains the audit daemon.
+endef
+
+CONFIGURE_VARS += \
+	LDFLAGS_FOR_BUILD="$(HOST_LDFLAGS)" \
+	CPPFLAGS_FOR_BUILD="$(HOST_CPPFLAGS)" \
+	CFLAGS_FOR_BUILD="$(HOST_CFLAGS)" \
+	CC_FOR_BUILD="$(HOSTCC)"
+
+CONFIGURE_ARGS += \
+	--with-debug \
+	--disable-systemd \
+	--disable-zos-remote \
+	--disable-gssapi-krb5 \
+	--without-libcap-ng \
+	--without-python \
+	--without-python3 \
+	--without-golang
+
+ifeq ($(ARCH),aarch64)
+CONFIGURE_ARGS += --with-aarch64
+else ifeq ($(ARCH),arm)
+CONFIGURE_ARGS += --with-arm
+endif
+
+HOST_CONFIGURE_ARGS += \
+	--disable-systemd \
+	--disable-zos-remote \
+	--disable-gssapi-krb5 \
+	--without-libcap-ng \
+	--without-python \
+	--without-python3 \
+	--without-golang
+
+define Host/Install
+	+$(HOST_MAKE_VARS) $(MAKE) $(HOST_JOBS) -C $(HOST_BUILD_DIR)/lib $(HOST_MAKE_FLAGS) install
+	+$(HOST_MAKE_VARS) $(MAKE) $(HOST_JOBS) -C $(HOST_BUILD_DIR)/init.d $(HOST_MAKE_FLAGS) install
+endef
+
+# We can't use the default, as the default passes $(MAKE_ARGS), which
+# overrides CC, CFLAGS, etc. and defeats the *_FOR_BUILD definitions
+# passed in CONFIGURE_VARS
+define Build/Compile
+	$(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR)/$(MAKE_PATH)
+endef
+
+define Build/Install
+	$(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR)/lib $(MAKE_INSTALL_FLAGS) install
+	$(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR)/init.d $(MAKE_INSTALL_FLAGS) install
+	$(call Build/Install/Default,install)
+endef
+
+define Build/InstallDev
+	$(INSTALL_DIR) $(1)/usr/include
+	$(CP) $(PKG_INSTALL_DIR)/usr/include/* $(1)/usr/include/
+	$(INSTALL_DIR) $(1)/usr/lib/pkgconfig
+	$(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/*.pc $(1)/usr/lib/pkgconfig/
+	$(INSTALL_DIR) $(1)/usr/lib
+	$(CP) $(PKG_INSTALL_DIR)/usr/lib/* $(1)/usr/lib/
+endef
+
+define Package/libaudit/install
+	$(INSTALL_DIR) $(1)/usr/lib
+	$(CP) $(PKG_INSTALL_DIR)/usr/lib/libaudit.so* $(1)/usr/lib/
+	$(INSTALL_DIR) $(1)/etc
+	$(CP) $(PKG_INSTALL_DIR)/etc/libaudit.conf $(1)/etc/
+endef
+
+define Package/libauparse/install
+	$(INSTALL_DIR) $(1)/usr/lib
+	$(CP) $(PKG_INSTALL_DIR)/usr/lib/libauparse.so* $(1)/usr/lib/
+endef
+
+define Package/audit-utils/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(CP) $(PKG_INSTALL_DIR)/usr/bin/* $(1)/usr/bin/
+	$(INSTALL_DIR) $(1)/usr/sbin
+	$(CP) \
+		$(PKG_INSTALL_DIR)/usr/sbin/{audisp-remote,audisp-syslog,auditctl,augenrules,aureport,ausearch,autrace} \
+		$(1)/usr/sbin/
+endef
+
+define Package/auditd/install
+	$(INSTALL_DIR) $(1)/etc/audit
+	$(CP) $(PKG_INSTALL_DIR)/etc/audit/* $(1)/etc/audit/
+	# af_unix plugin is not installed. Remove it's .conf.
+	if [[ -f $(1)/etc/audit/plugins.d/af_unix.conf ]] ; then rm $(1)/etc/audit/plugins.d/af_unix.conf ; fi
+	$(INSTALL_DIR) $(1)/etc/init.d
+	$(INSTALL_BIN) ./files/audit.init $(1)/etc/init.d/audit
+	$(INSTALL_DIR) $(1)/usr/sbin
+	$(CP) $(PKG_INSTALL_DIR)/usr/sbin/auditd $(1)/usr/sbin/
+endef
+
+$(eval $(call HostBuild))
+$(eval $(call BuildPackage,libaudit))
+$(eval $(call BuildPackage,libauparse))
+$(eval $(call BuildPackage,audit-utils))
+$(eval $(call BuildPackage,auditd))
diff --git a/package/utils/audit/files/audit.init b/package/utils/audit/files/audit.init
new file mode 100644
index 0000000..4a9f538
--- /dev/null
+++ b/package/utils/audit/files/audit.init
@@ -0,0 +1,16 @@
+#!/bin/sh /etc/rc.common
+# Copyright (c) 2014 OpenWrt.org
+
+START=11
+
+USE_PROCD=1
+PROG=/usr/sbin/auditd
+
+start_service() {
+	mkdir -p /var/log/audit
+	procd_open_instance
+	procd_set_param command "$PROG" -n
+	procd_set_param respawn
+	procd_close_instance
+	test -f /etc/audit/rules.d/audit.rules && /usr/sbin/auditctl -R /etc/audit/rules.d/audit.rules
+}
diff --git a/package/utils/bcm27xx-utils/Makefile b/package/utils/bcm27xx-utils/Makefile
new file mode 100644
index 0000000..04dd6b8
--- /dev/null
+++ b/package/utils/bcm27xx-utils/Makefile
@@ -0,0 +1,64 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=bcm27xx-utils
+PKG_VERSION:=2024-04-24
+PKG_RELEASE:=1
+
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_URL:=https://github.com/raspberrypi/utils.git
+PKG_SOURCE_VERSION:=451b9881b72cb994c102724b5a7d9b93f97dc315
+PKG_MIRROR_HASH:=b453976171187e0ffe7cacfdcab36cec6b5d02db8b6d978cb9afbbcafcfcff9d
+
+PKG_FLAGS:=nonshared
+PKG_BUILD_FLAGS:=no-lto
+
+PKG_LICENSE:=BSD-3-Clause
+PKG_LICENSE_FILES:=LICENCE
+
+CMAKE_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/cmake.mk
+
+define Package/bcm27xx-utils
+  SECTION:=utils
+  CATEGORY:=Utilities
+  DEPENDS:=@TARGET_bcm27xx +libfdt
+  TITLE:=BCM27xx scripts and simple applications
+  PROVIDES:=bcm27xx-userland
+endef
+
+define Package/bcm27xx-utils/description
+  BCM27xx scripts and simple applications.
+  Replaces bcm27xx-userland scripts and applications.
+endef
+
+define Package/bcm27xx-utils/install
+	$(INSTALL_DIR) $(1)/usr/bin
+
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/dtmerge $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/dtoverlay $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/dtparam $(1)/usr/bin
+
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/eepdump $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/eepflash.sh $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/eepmake $(1)/usr/bin
+
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/otpset $(1)/usr/bin
+
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/overlaycheck $(1)/usr/bin
+	$(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/bin/overlaycheck_exclusions.txt $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/ovmerge $(1)/usr/bin
+
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/pinctrl $(1)/usr/bin
+
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/raspinfo $(1)/usr/bin
+
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/vcgencmd $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/vclog $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/vcmailbox $(1)/usr/bin
+endef
+
+$(eval $(call BuildPackage,bcm27xx-utils))
diff --git a/package/utils/bcm27xx-utils/patches/0001-raspinfo-adapt-to-OpenWrt.patch b/package/utils/bcm27xx-utils/patches/0001-raspinfo-adapt-to-OpenWrt.patch
new file mode 100644
index 0000000..9dd6d99
--- /dev/null
+++ b/package/utils/bcm27xx-utils/patches/0001-raspinfo-adapt-to-OpenWrt.patch
@@ -0,0 +1,255 @@
+From 0db3fb3119eda8c2360454c2a01f84602a879c38 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= <noltari@gmail.com>
+Date: Tue, 16 Jan 2024 15:32:12 +0100
+Subject: [PATCH] raspinfo: adapt to OpenWrt
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
+---
+ raspinfo/raspinfo | 186 ++++------------------------------------------
+ 1 file changed, 13 insertions(+), 173 deletions(-)
+
+--- a/raspinfo/raspinfo
++++ b/raspinfo/raspinfo
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/bin/sh
+ 
+ # Some of the regex's used in sed
+ # Catch basic IP6 address   "s/\([0-9a-fA-F]\{1,4\}:\)\{7,7\}[0-9a-fA-F]\{1,4\}/y.y.y.y.y.y.y.y/g"
+@@ -6,147 +6,6 @@
+ # IP4 d.d.d.d decimal	    "s/\([0-9]\{1,3\}\.\)\{3,3\}[0-9]\{1,3\}/x.x.x.x/g"
+ # mac address	            "s/\([0-9a-fA-F]\{2,2\}\:\)\{5,5\}[0-9a-fA-F]\{2,2\}/m.m.m.m/g"
+ 
+-
+-display_info_drm() {
+-   # If running X then can use xrandr, otherwise
+-   # dump the /sys/class entries for the displays
+-   if command -v xrandr > /dev/null &&
+-      DISPLAY=${DISPLAY:-:0} xrandr --listmonitors &>/dev/null;
+-   then
+-      echo "Running (F)KMS and X"
+-      echo
+-
+-      DISPLAY=${DISPLAY:-:0} xrandr --verbose
+-   else
+-      echo "Running (F)KMS, console"
+-      echo
+-
+-      for card in /sys/class/drm/card[0-9]-*;
+-      do
+-         echo $card
+-
+-         # if kmsprint isn't installed print basic mode info
+-         if ! command -v kmsprint > /dev/null; then
+-            if [ -f $card/modes ];
+-            then
+-               cat $card/modes
+-            else
+-               echo "No modes found"
+-            fi
+-         fi
+-
+-         if [ -f $card/edid ];
+-         then
+-            base64 $card/edid
+-         else
+-            echo "No EDID found"
+-         fi
+-         echo
+-      done
+-   fi
+-
+-   # kmsprint is more useful, but not always installed
+-   echo
+-   if command -v kmsprint > /dev/null; then
+-      kmsprint
+-      echo
+-      kmsprint -m
+-   else
+-      echo "kmsprint is not installed. Install with: sudo apt install kms++-utils"
+-   fi
+-
+-   echo
+-
+-   # dump the /sys/class entries for the displays
+-   cardfound=0
+-   for card in `seq 0 9`;
+-   do
+-      if sudo test -f "/sys/kernel/debug/dri/${card}/state";
+-      then
+-        for hdmi in 0 1;
+-        do
+-         if sudo test -f "/sys/kernel/debug/dri/${card}/hdmi${hdmi}_regs";
+-         then
+-            echo "HDMI${hdmi}: $(sudo cat /sys/kernel/debug/dri/$card/hdmi${hdmi}_regs | grep HOTPLUG)"
+-         fi
+-      done
+-      echo
+-      echo "/sys/kernel/debug/dri/$card/state:"
+-      sudo cat "/sys/kernel/debug/dri/$card/state"
+-      echo
+-      cardfound=1
+-      fi
+-   done
+-   if [ "$cardfound" == "0" ];
+-   then
+-      echo "kms state not found"
+-   fi
+-   echo
+-
+-}
+-
+-display_info_legacy() {
+-   # Legacy mode
+-   echo "Running Legacy framebuffer"
+-   echo
+-
+-   for card in `seq 0 9`;
+-   do
+-      F="/dev/fb${card}"
+-      if test -e $F;
+-      then
+-         echo Framebuffer: $F
+-         fbset -s -fb $F
+-      fi
+-   done
+-
+-   disps=`tvservice -l | awk '/Display Number/{print substr($3,1,1)}'`
+-
+-   tmp=$(mktemp)
+-
+-   for display in $disps
+-   do
+-      echo
+-      echo "Display: " $display
+-
+-      tvservice -v $display -s
+-      tvservice -v $display -n
+-      tvservice -v $display -m CEA
+-      tvservice -v $display -m DMT
+-
+-      echo
+-      tvservice -v $display -d $tmp > /dev/null
+-      base64 $tmp
+-   done
+-
+-   rm $tmp
+-}
+-
+-display_info() {
+-   # Check if we are running a KMS/DRM system
+-
+-   if [ -d "/dev/dri" ];
+-   then
+-      display_info_drm
+-   else
+-      display_info_legacy
+-   fi
+-}
+-
+-audio_info() {
+-   aplay -l
+-   echo
+-   aplay -L
+-   echo
+-   systemctl --user status pipewire.socket pipewire.service pulseaudio.service pulseaudio.socket
+-   echo
+-   if command -v pactl > /dev/null; then
+-      pactl info
+-   else
+-      echo pactl not installed
+-   fi
+-}
+-
+ OUT=raspinfo.txt
+ 
+ rm -f $OUT
+@@ -163,8 +22,6 @@ echo
+ cat /etc/os-release | head -4
+ echo
+ 
+-cat /etc/rpi-issue
+-echo
+ uname -a
+ 
+ cat /proc/cpuinfo | tail -3
+@@ -190,17 +47,6 @@ echo
+ cat /proc/swaps
+ 
+ echo
+-echo "Package version information"
+-echo "---------------------------"
+-
+-apt-cache policy raspberrypi-ui-mods | head -2
+-apt-cache policy raspberrypi-sys-mods | head -2
+-apt-cache policy openbox | head -2
+-apt-cache policy lxpanel | head -2
+-apt-cache policy pcmanfm | head -2
+-apt-cache policy rpd-plym-splash | head -2
+-
+-echo
+ echo "Networking Information"
+ echo "----------------------"
+ echo
+@@ -212,21 +58,11 @@ echo "USB Information"
+ echo "---------------"
+ echo
+ 
+-lsusb -t
+-
+-echo
+-echo "Display Information"
+-echo "-------------------"
+-echo
+-
+-display_info
+-
+-echo
+-echo "Audio Information"
+-echo "-------------------"
+-echo
+-
+-audio_info
++if command -v lsusb > /dev/null; then
++   lsusb -t
++else
++   echo usbutils not installed
++fi
+ 
+ echo
+ echo "config.txt"
+@@ -250,7 +86,7 @@ echo "-----------------"
+ echo
+ 
+ if command -v pinctrl > /dev/null; then
+-   sudo pinctrl 2>&1
++   pinctrl 2>&1
+ elif command -v raspi-gpio > /dev/null; then
+    raspi-gpio get 2>&1
+ else
+@@ -263,9 +99,9 @@ echo "------------------"
+ echo
+ 
+ if command -v vcdbg > /dev/null; then
+-   sudo vcdbg log msg 2>&1
++   vcdbg log msg 2>&1
+ elif command -v vclog > /dev/null; then
+-   sudo vclog --msg 2>&1
++   vclog --msg 2>&1
+ else
+    echo "vcdbg not found"
+ fi
+@@ -284,5 +120,9 @@ echo
+ echo "EEPROM"
+ echo "------"
+ echo
+-sudo rpi-eeprom-update
++if command -v rpi-eeprom-update > /dev/null; then
++   rpi-eeprom-update
++else
++   echo bcm27xx-eeprom not installed
++fi
+ fi
diff --git a/package/utils/bcm4908img/Makefile b/package/utils/bcm4908img/Makefile
new file mode 100644
index 0000000..fbb91fb
--- /dev/null
+++ b/package/utils/bcm4908img/Makefile
@@ -0,0 +1,54 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=bcm4908img
+PKG_RELEASE:=3
+
+PKG_FLAGS:=nonshared
+
+PKG_BUILD_DEPENDS := bcm4908img/host
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/host-build.mk
+
+define Package/bcm4908img
+  SECTION:=utils
+  CATEGORY:=Base system
+  TITLE:=Utility handling BCM4908 images
+  MAINTAINER:=Rafał Miłecki <rafal@milecki.pl>
+  DEPENDS:=@TARGET_bcm4908
+endef
+
+define Package/bcm4908img/description
+  CFE bootloader for BCM4908 uses custom image format. It consists of:
+  1. Optional cferom image
+  2. bootfs JFFS2 partition (cferam, kernel, DTB and optional helper files)
+  3. padding
+  4. rootfs simply appended to the bootfs + padding
+  5. tail with checksum and basic device info
+
+  This util allows creating, modifying and extracting from BCM4908 images.
+endef
+
+define Host/Prepare
+  $(CP) ./src/* $(HOST_BUILD_DIR)
+endef
+
+define Build/Compile
+	$(MAKE) -C $(PKG_BUILD_DIR) \
+		CC="$(TARGET_CC)" \
+		CFLAGS="$(TARGET_CFLAGS) -Wall"
+endef
+
+define Package/bcm4908img/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/bcm4908img $(1)/usr/bin/
+endef
+
+define Host/Install
+	$(INSTALL_BIN) $(HOST_BUILD_DIR)/bcm4908img $(STAGING_DIR_HOST)/bin/
+endef
+
+$(eval $(call BuildPackage,bcm4908img))
+$(eval $(call HostBuild))
diff --git a/package/utils/bcm4908img/src/Makefile b/package/utils/bcm4908img/src/Makefile
new file mode 100644
index 0000000..72f8e30
--- /dev/null
+++ b/package/utils/bcm4908img/src/Makefile
@@ -0,0 +1,7 @@
+all: bcm4908img
+
+bcm4908img:
+	$(CC) $(CFLAGS) -o $@ bcm4908img.c -Wall
+
+clean:
+	rm -f bcm4908img
diff --git a/package/utils/bcm4908img/src/bcm4908img.c b/package/utils/bcm4908img/src/bcm4908img.c
new file mode 100644
index 0000000..240fe89
--- /dev/null
+++ b/package/utils/bcm4908img/src/bcm4908img.c
@@ -0,0 +1,1022 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2021 Rafał Miłecki <rafal@milecki.pl>
+ */
+
+#include <byteswap.h>
+#include <endian.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#if !defined(__BYTE_ORDER)
+#error "Unknown byte order"
+#endif
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+#define cpu_to_le32(x)	bswap_32(x)
+#define le32_to_cpu(x)	bswap_32(x)
+#define cpu_to_be32(x)	(x)
+#define be32_to_cpu(x)	(x)
+#define cpu_to_le16(x)	bswap_16(x)
+#define le16_to_cpu(x)	bswap_16(x)
+#define cpu_to_be16(x)	(x)
+#define be16_to_cpu(x)	(x)
+#elif __BYTE_ORDER == __LITTLE_ENDIAN
+#define cpu_to_le32(x)	(x)
+#define le32_to_cpu(x)	(x)
+#define cpu_to_be32(x)	bswap_32(x)
+#define be32_to_cpu(x)	bswap_32(x)
+#define cpu_to_le16(x)	(x)
+#define le16_to_cpu(x)	(x)
+#define cpu_to_be16(x)	bswap_16(x)
+#define be16_to_cpu(x)	bswap_16(x)
+#else
+#error "Unsupported endianness"
+#endif
+
+#define WFI_VERSION			0x00005732
+#define WFI_VERSION_NAND_1MB_DATA	0x00005731
+
+#define WFI_NOR_FLASH			1
+#define WFI_NAND16_FLASH		2
+#define WFI_NAND128_FLASH		3
+#define WFI_NAND256_FLASH		4
+#define WFI_NAND512_FLASH		5
+#define WFI_NAND1024_FLASH		6
+#define WFI_NAND2048_FLASH		7
+
+#define WFI_FLAG_HAS_PMC		0x1
+#define WFI_FLAG_SUPPORTS_BTRM		0x2
+
+#define UBI_EC_HDR_MAGIC		0x55424923
+
+static int debug;
+
+struct bcm4908img_tail {
+	uint32_t crc32;
+	uint32_t version;
+	uint32_t chip_id;
+	uint32_t flash_type;
+	uint32_t flags;
+};
+
+/**
+ * struct bcm4908img_info - info about BCM4908 image
+ *
+ * Standard BCM4908 image consists of:
+ * 1. (Optional) vedor header
+ * 2. (Optional) cferom
+ * 3. bootfs  ─┐
+ * 4. padding  ├─ firmware
+ * 5. rootfs  ─┘
+ * 6. BCM4908 tail
+ * 7. (Optional) vendor tail
+ */
+struct bcm4908img_info {
+	size_t cferom_offset;
+	size_t bootfs_offset;
+	size_t padding_offset;
+	size_t rootfs_offset;
+	size_t tail_offset;
+	uint32_t crc32;			/* Calculated checksum */
+	struct bcm4908img_tail tail;
+};
+
+char *pathname;
+
+static inline size_t bcm4908img_min(size_t x, size_t y) {
+	return x < y ? x : y;
+}
+
+/**************************************************
+ * CRC32
+ **************************************************/
+
+static const uint32_t crc32_tbl[] = {
+	0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
+	0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
+	0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+	0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
+	0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+	0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+	0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
+	0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
+	0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+	0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+	0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
+	0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+	0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
+	0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
+	0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+	0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
+	0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
+	0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+	0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
+	0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+	0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+	0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
+	0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
+	0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+	0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+	0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
+	0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+	0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
+	0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
+	0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+	0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
+	0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
+	0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+	0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
+	0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+	0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+	0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
+	0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
+	0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+	0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+	0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
+	0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+	0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
+	0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
+	0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+	0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
+	0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
+	0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+	0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
+	0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+	0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+	0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
+	0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
+	0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+	0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+	0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
+	0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+	0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
+	0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
+	0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+	0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
+	0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
+	0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+	0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
+};
+
+uint32_t bcm4908img_crc32(uint32_t crc, const void *buf, size_t len) {
+	const uint8_t *in = buf;
+
+	while (len) {
+		crc = crc32_tbl[(crc ^ *in) & 0xff] ^ (crc >> 8);
+		in++;
+		len--;
+	}
+
+	return crc;
+}
+
+/**************************************************
+ * Helpers
+ **************************************************/
+
+static FILE *bcm4908img_open(const char *pathname, const char *mode) {
+	struct stat st;
+
+	if (pathname)
+		return fopen(pathname, mode);
+
+	if (isatty(fileno(stdin))) {
+		fprintf(stderr, "Reading from TTY stdin is unsupported\n");
+		return NULL;
+	}
+
+	if (fstat(fileno(stdin), &st)) {
+		fprintf(stderr, "Failed to fstat stdin: %d\n", -errno);
+		return NULL;
+	}
+
+	if (S_ISFIFO(st.st_mode)) {
+		fprintf(stderr, "Reading from pipe stdin is unsupported\n");
+		return NULL;
+	}
+
+	return stdin;
+}
+
+static void bcm4908img_close(FILE *fp) {
+	if (fp != stdin)
+		fclose(fp);
+}
+
+static int bcm4908img_calc_crc32(FILE *fp, struct bcm4908img_info *info) {
+	uint8_t buf[1024];
+	size_t length;
+	size_t bytes;
+
+	/* Start with cferom (or bootfs) - skip vendor header */
+	fseek(fp, info->cferom_offset, SEEK_SET);
+
+	info->crc32 = 0xffffffff;
+	length = info->tail_offset - info->cferom_offset;
+	while (length && (bytes = fread(buf, 1, bcm4908img_min(sizeof(buf), length), fp)) > 0) {
+		info->crc32 = bcm4908img_crc32(info->crc32, buf, bytes);
+		length -= bytes;
+	}
+	if (length) {
+		fprintf(stderr, "Failed to read last %zd B of data\n", length);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+/**************************************************
+ * Existing firmware parser
+ **************************************************/
+
+struct chk_header {
+	uint32_t magic;
+	uint32_t header_len;
+	uint8_t  reserved[8];
+	uint32_t kernel_chksum;
+	uint32_t rootfs_chksum;
+	uint32_t kernel_len;
+	uint32_t rootfs_len;
+	uint32_t image_chksum;
+	uint32_t header_chksum;
+	char board_id[0];
+};
+
+struct linksys_tail {
+	char magic[9];
+	uint8_t version[8];
+	char model[15];
+	uint32_t crc32;
+	uint8_t padding[9];
+	uint8_t signature[16];
+	uint8_t reserved[192];
+};
+
+static bool bcm4908img_is_all_ff(const void *buf, size_t length)
+{
+	const uint8_t *in = buf;
+	int i;
+
+	for (i = 0; i < length; i++) {
+		if (in[i] != 0xff)
+			return false;
+	}
+
+	return true;
+}
+
+static int bcm4908img_parse(FILE *fp, struct bcm4908img_info *info) {
+	struct bcm4908img_tail *tail = &info->tail;
+	struct linksys_tail *linksys;
+	struct chk_header *chk;
+	struct stat st;
+	uint8_t buf[1024];
+	size_t file_size;
+	uint16_t tmp16;
+	size_t length;
+	size_t bytes;
+	int err = 0;
+
+	memset(info, 0, sizeof(*info));
+
+	/* File size */
+
+	if (fstat(fileno(fp), &st)) {
+		err = -errno;
+		fprintf(stderr, "Failed to fstat: %d\n", err);
+		return err;
+	}
+	file_size = st.st_size;
+
+	info->tail_offset = file_size - sizeof(*tail);
+
+	/* Vendor formats */
+
+	rewind(fp);
+	if (fread(buf, 1, sizeof(buf), fp) != sizeof(buf)) {
+		fprintf(stderr, "Failed to read file header\n");
+		return -EIO;
+	}
+	chk = (void *)buf;
+	if (be32_to_cpu(chk->magic) == 0x2a23245e)
+		info->cferom_offset = be32_to_cpu(chk->header_len);
+
+	fseek(fp, -sizeof(buf), SEEK_END);
+	if (fread(buf, 1, sizeof(buf), fp) != sizeof(buf)) {
+		fprintf(stderr, "Failed to read file header\n");
+		return -EIO;
+	}
+	linksys = (void *)(buf + sizeof(buf) - sizeof(*linksys));
+	if (!memcmp(linksys->magic, ".LINKSYS.", sizeof(linksys->magic))) {
+		info->tail_offset -= sizeof(*linksys);
+	}
+
+	/* Offsets */
+
+	for (info->bootfs_offset = info->cferom_offset;
+	     info->bootfs_offset < info->tail_offset;
+	     info->bootfs_offset += 0x20000) {
+		if (fseek(fp, info->bootfs_offset, SEEK_SET)) {
+			err = -errno;
+			fprintf(stderr, "Failed to fseek to the 0x%zx\n", info->bootfs_offset);
+			return err;
+		}
+		if (fread(&tmp16, 1, sizeof(tmp16), fp) != sizeof(tmp16)) {
+			fprintf(stderr, "Failed to read while looking for JFFS2\n");
+			return -EIO;
+		}
+		if (be16_to_cpu(tmp16) == 0x8519)
+			break;
+	}
+	if (info->bootfs_offset >= info->tail_offset) {
+		fprintf(stderr, "Failed to find bootfs offset\n");
+		return -EPROTO;
+	}
+
+	for (info->rootfs_offset = info->bootfs_offset;
+	     info->rootfs_offset < info->tail_offset;
+	     info->rootfs_offset += 0x20000) {
+		uint32_t *magic = (uint32_t *)&buf[0];
+
+		if (fseek(fp, info->rootfs_offset, SEEK_SET)) {
+			err = -errno;
+			fprintf(stderr, "Failed to fseek: %d\n", err);
+			return err;
+		}
+
+		length = info->padding_offset ? sizeof(*magic) : 256;
+		bytes = fread(buf, 1, length, fp);
+		if (bytes != length) {
+			fprintf(stderr, "Failed to read %zu bytes\n", length);
+			return -EIO;
+		}
+
+		if (!info->padding_offset && bcm4908img_is_all_ff(buf, length))
+			info->padding_offset = info->rootfs_offset;
+
+		if (be32_to_cpu(*magic) == UBI_EC_HDR_MAGIC)
+			break;
+	}
+	if (info->rootfs_offset >= info->tail_offset) {
+		fprintf(stderr, "Failed to find rootfs offset\n");
+		return -EPROTO;
+	}
+
+	/* CRC32 */
+
+	/* Start with cferom (or bootfs) - skip vendor header */
+	fseek(fp, info->cferom_offset, SEEK_SET);
+
+	info->crc32 = 0xffffffff;
+	length = info->tail_offset - info->cferom_offset;
+	while (length && (bytes = fread(buf, 1, bcm4908img_min(sizeof(buf), length), fp)) > 0) {
+		info->crc32 = bcm4908img_crc32(info->crc32, buf, bytes);
+		length -= bytes;
+	}
+	if (length) {
+		fprintf(stderr, "Failed to read last %zd B of data\n", length);
+		return -EIO;
+	}
+
+	/* Tail */
+
+	if (fread(tail, 1, sizeof(*tail), fp) != sizeof(*tail)) {
+		fprintf(stderr, "Failed to read BCM4908 image tail\n");
+		return -EIO;
+	}
+
+	/* Standard validation */
+
+	if (info->crc32 != le32_to_cpu(tail->crc32)) {
+		fprintf(stderr, "Invalid data crc32: 0x%08x instead of 0x%08x\n", info->crc32, le32_to_cpu(tail->crc32));
+		return -EPROTO;
+	}
+
+	return 0;
+}
+
+/**************************************************
+ * Info
+ **************************************************/
+
+static int bcm4908img_info(int argc, char **argv) {
+	struct bcm4908img_info info;
+	const char *pathname = NULL;
+	FILE *fp;
+	int c;
+	int err = 0;
+
+	while ((c = getopt(argc, argv, "i:")) != -1) {
+		switch (c) {
+		case 'i':
+			pathname = optarg;
+			break;
+		}
+	}
+
+	fp = bcm4908img_open(pathname, "r");
+	if (!fp) {
+		fprintf(stderr, "Failed to open BCM4908 image\n");
+		err = -EACCES;
+		goto out;
+	}
+
+	err = bcm4908img_parse(fp, &info);
+	if (err) {
+		fprintf(stderr, "Failed to parse BCM4908 image\n");
+		goto err_close;
+	}
+
+	if (info.bootfs_offset != info.cferom_offset)
+		printf("cferom offset:\t%zu\n", info.cferom_offset);
+	printf("bootfs offset:\t0x%zx\n", info.bootfs_offset);
+	if (info.padding_offset)
+		printf("padding offset:\t0x%zx\n", info.padding_offset);
+	printf("rootfs offset:\t0x%zx\n", info.rootfs_offset);
+	printf("Checksum:\t0x%08x\n", info.crc32);
+
+err_close:
+	bcm4908img_close(fp);
+out:
+	return err;
+}
+
+/**************************************************
+ * Create
+ **************************************************/
+
+static ssize_t bcm4908img_create_append_file(FILE *trx, const char *in_path, uint32_t *crc32) {
+	FILE *in;
+	size_t bytes;
+	ssize_t length = 0;
+	uint8_t buf[1024];
+
+	in = fopen(in_path, "r");
+	if (!in) {
+		fprintf(stderr, "Failed to open %s\n", in_path);
+		return -EACCES;
+	}
+
+	while ((bytes = fread(buf, 1, sizeof(buf), in)) > 0) {
+		if (fwrite(buf, 1, bytes, trx) != bytes) {
+			fprintf(stderr, "Failed to write %zu B to %s\n", bytes, pathname);
+			length = -EIO;
+			break;
+		}
+		*crc32 = bcm4908img_crc32(*crc32, buf, bytes);
+		length += bytes;
+	}
+
+	fclose(in);
+
+	return length;
+}
+
+static ssize_t bcm4908img_create_append_zeros(FILE *trx, size_t length) {
+	uint8_t *buf;
+
+	buf = malloc(length);
+	if (!buf)
+		return -ENOMEM;
+	memset(buf, 0, length);
+
+	if (fwrite(buf, 1, length, trx) != length) {
+		fprintf(stderr, "Failed to write %zu B to %s\n", length, pathname);
+		free(buf);
+		return -EIO;
+	}
+
+	free(buf);
+
+	return length;
+}
+
+static ssize_t bcm4908img_create_align(FILE *trx, size_t cur_offset, size_t alignment) {
+	if (cur_offset & (alignment - 1)) {
+		size_t length = alignment - (cur_offset % alignment);
+		return bcm4908img_create_append_zeros(trx, length);
+	}
+
+	return 0;
+}
+
+static int bcm4908img_create(int argc, char **argv) {
+	struct bcm4908img_tail tail = {
+		.version = cpu_to_le32(WFI_VERSION),
+		.chip_id = cpu_to_le32(0x4908),
+		.flash_type = cpu_to_le32(WFI_NAND128_FLASH),
+		.flags = cpu_to_le32(WFI_FLAG_SUPPORTS_BTRM),
+	};
+	uint32_t crc32 = 0xffffffff;
+	size_t cur_offset = 0;
+	ssize_t bytes;
+	FILE *fp;
+	int c;
+	int err = 0;
+
+	if (argc < 3) {
+		fprintf(stderr, "No BCM4908 image pathname passed\n");
+		err = -EINVAL;
+		goto out;
+	}
+	pathname = argv[2];
+
+	fp = fopen(pathname, "w+");
+	if (!fp) {
+		fprintf(stderr, "Failed to open %s\n", pathname);
+		err = -EACCES;
+		goto out;
+	}
+
+	optind = 3;
+	while ((c = getopt(argc, argv, "f:a:A:")) != -1) {
+		switch (c) {
+		case 'f':
+			bytes = bcm4908img_create_append_file(fp, optarg, &crc32);
+			if (bytes < 0) {
+				fprintf(stderr, "Failed to append file %s\n", optarg);
+			} else {
+				cur_offset += bytes;
+			}
+			break;
+		case 'a':
+			bytes = bcm4908img_create_align(fp, cur_offset, strtol(optarg, NULL, 0));
+			if (bytes < 0)
+				fprintf(stderr, "Failed to append zeros\n");
+			else
+				cur_offset += bytes;
+			break;
+		case 'A':
+			bytes = strtol(optarg, NULL, 0) - cur_offset;
+			if (bytes < 0) {
+				fprintf(stderr, "Current BCM4908 image length is 0x%zx, can't pad it with zeros to 0x%lx\n", cur_offset, strtol(optarg, NULL, 0));
+			} else {
+				bytes = bcm4908img_create_append_zeros(fp, bytes);
+				if (bytes < 0)
+					fprintf(stderr, "Failed to append zeros\n");
+				else
+					cur_offset += bytes;
+			}
+			break;
+		}
+		if (err)
+			goto err_close;
+	}
+
+	tail.crc32 = cpu_to_le32(crc32);
+
+	bytes = fwrite(&tail, 1, sizeof(tail), fp);
+	if (bytes != sizeof(tail)) {
+		fprintf(stderr, "Failed to write BCM4908 image tail to %s\n", pathname);
+		return -EIO;
+	}
+
+err_close:
+	fclose(fp);
+out:
+	return err;
+}
+
+/**************************************************
+ * Extract
+ **************************************************/
+
+static int bcm4908img_extract(int argc, char **argv) {
+	struct bcm4908img_info info;
+	const char *pathname = NULL;
+	const char *type = NULL;
+	uint8_t buf[1024];
+	size_t offset;
+	size_t length;
+	size_t bytes;
+	FILE *fp;
+	int c;
+	int err = 0;
+
+	while ((c = getopt(argc, argv, "i:t:")) != -1) {
+		switch (c) {
+		case 'i':
+			pathname = optarg;
+			break;
+		case 't':
+			type = optarg;
+			break;
+		}
+	}
+
+	fp = bcm4908img_open(pathname, "r");
+	if (!fp) {
+		fprintf(stderr, "Failed to open BCM4908 image\n");
+		err = -EACCES;
+		goto err_out;
+	}
+
+	err = bcm4908img_parse(fp, &info);
+	if (err) {
+		fprintf(stderr, "Failed to parse BCM4908 image\n");
+		goto err_close;
+	}
+
+	if (!type) {
+		err = -EINVAL;
+		fprintf(stderr, "No data to extract specified\n");
+		goto err_close;
+	} else if (!strcmp(type, "cferom")) {
+		offset = info.cferom_offset;
+		length = info.bootfs_offset - offset;
+		if (!length) {
+			err = -ENOENT;
+			fprintf(stderr, "This BCM4908 image doesn't contain cferom\n");
+			goto err_close;
+		}
+	} else if (!strcmp(type, "bootfs")) {
+		offset = info.bootfs_offset;
+		length = (info.padding_offset ? info.padding_offset : info.rootfs_offset) - offset;
+	} else if (!strcmp(type, "rootfs")) {
+		offset = info.rootfs_offset;
+		length = info.tail_offset - offset;
+	} else if (!strcmp(type, "firmware")) {
+		offset = info.bootfs_offset;
+		length = info.tail_offset - offset;
+	} else {
+		err = -EINVAL;
+		fprintf(stderr, "Unsupported extract type: %s\n", type);
+		goto err_close;
+	}
+
+	if (!length) {
+		err = -EINVAL;
+		fprintf(stderr, "Failed to find requested data in input image\n");
+		goto err_close;
+	}
+
+	fseek(fp, offset, SEEK_SET);
+	while (length && (bytes = fread(buf, 1, bcm4908img_min(sizeof(buf), length), fp)) > 0) {
+		fwrite(buf, bytes, 1, stdout);
+		length -= bytes;
+	}
+	if (length) {
+		err = -EIO;
+		fprintf(stderr, "Failed to read last %zd B of data\n", length);
+		goto err_close;
+	}
+
+err_close:
+	bcm4908img_close(fp);
+err_out:
+	return err;
+}
+
+/**************************************************
+ * bootfs
+ **************************************************/
+
+#define JFFS2_MAGIC_BITMASK 0x1985
+
+#define JFFS2_COMPR_NONE	0x00
+#define JFFS2_COMPR_ZERO	0x01
+#define JFFS2_COMPR_RTIME	0x02
+#define JFFS2_COMPR_RUBINMIPS	0x03
+#define JFFS2_COMPR_COPY	0x04
+#define JFFS2_COMPR_DYNRUBIN	0x05
+#define JFFS2_COMPR_ZLIB	0x06
+#define JFFS2_COMPR_LZO		0x07
+/* Compatibility flags. */
+#define JFFS2_COMPAT_MASK 0xc000      /* What do to if an unknown nodetype is found */
+#define JFFS2_NODE_ACCURATE 0x2000
+/* INCOMPAT: Fail to mount the filesystem */
+#define JFFS2_FEATURE_INCOMPAT 0xc000
+/* ROCOMPAT: Mount read-only */
+#define JFFS2_FEATURE_ROCOMPAT 0x8000
+/* RWCOMPAT_COPY: Mount read/write, and copy the node when it's GC'd */
+#define JFFS2_FEATURE_RWCOMPAT_COPY 0x4000
+/* RWCOMPAT_DELETE: Mount read/write, and delete the node when it's GC'd */
+#define JFFS2_FEATURE_RWCOMPAT_DELETE 0x0000
+
+#define JFFS2_NODETYPE_DIRENT (JFFS2_FEATURE_INCOMPAT | JFFS2_NODE_ACCURATE | 1)
+
+typedef struct {
+	uint32_t v32;
+} __attribute__((packed)) jint32_t;
+
+typedef struct {
+	uint16_t v16;
+} __attribute__((packed)) jint16_t;
+
+struct jffs2_unknown_node
+{
+	/* All start like this */
+	jint16_t magic;
+	jint16_t nodetype;
+	jint32_t totlen; /* So we can skip over nodes we don't grok */
+	jint32_t hdr_crc;
+};
+
+struct jffs2_raw_dirent
+{
+	jint16_t magic;
+	jint16_t nodetype;	/* == JFFS2_NODETYPE_DIRENT */
+	jint32_t totlen;
+	jint32_t hdr_crc;
+	jint32_t pino;
+	jint32_t version;
+	jint32_t ino; /* == zero for unlink */
+	jint32_t mctime;
+	uint8_t nsize;
+	uint8_t type;
+	uint8_t unused[2];
+	jint32_t node_crc;
+	jint32_t name_crc;
+	uint8_t name[0];
+};
+
+#define je16_to_cpu(x) ((x).v16)
+#define je32_to_cpu(x) ((x).v32)
+
+static int bcm4908img_bootfs_ls(FILE *fp, struct bcm4908img_info *info) {
+	struct jffs2_unknown_node node;
+	struct jffs2_raw_dirent dirent;
+	size_t offset;
+	size_t bytes;
+	int err = 0;
+
+	for (offset = info->bootfs_offset; ; offset += (je32_to_cpu(node.totlen) + 0x03) & ~0x03) {
+		char name[FILENAME_MAX + 1];
+
+		if (fseek(fp, offset, SEEK_SET)) {
+			err = -errno;
+			fprintf(stderr, "Failed to fseek: %d\n", err);
+			return err;
+		}
+
+		bytes = fread(&node, 1, sizeof(node), fp);
+		if (bytes != sizeof(node)) {
+			fprintf(stderr, "Failed to read %zu bytes\n", sizeof(node));
+			return -EIO;
+		}
+
+		if (je16_to_cpu(node.magic) != JFFS2_MAGIC_BITMASK) {
+			break;
+		}
+
+		if (je16_to_cpu(node.nodetype) != JFFS2_NODETYPE_DIRENT) {
+			continue;
+		}
+
+		memcpy(&dirent, &node, sizeof(node));
+		bytes += fread((uint8_t *)&dirent + sizeof(node), 1, sizeof(dirent) - sizeof(node), fp);
+		if (bytes != sizeof(dirent)) {
+			fprintf(stderr, "Failed to read %zu bytes\n", sizeof(node));
+			return -EIO;
+		}
+
+		if (dirent.nsize + 1 > sizeof(name)) {
+			/* Keep reading & printing BUT exit with error code */
+			fprintf(stderr, "Too long filename\n");
+			err = -ENOMEM;
+			continue;
+		}
+
+		bytes = fread(name, 1, dirent.nsize, fp);
+		if (bytes != dirent.nsize) {
+			fprintf(stderr, "Failed to read filename\n");
+			return -EIO;
+		}
+		name[bytes] = '\0';
+
+		printf("%s\n", name);
+	}
+
+	return err;
+}
+
+static int bcm4908img_bootfs_mv(FILE *fp, struct bcm4908img_info *info, int argc, char **argv) {
+	struct jffs2_unknown_node node;
+	struct jffs2_raw_dirent dirent;
+	const char *oldname;
+	const char *newname;
+	size_t offset;
+	size_t bytes;
+	int err = -ENOENT;
+
+	if (argc - optind < 2) {
+		fprintf(stderr, "No enough arguments passed\n");
+		return -EINVAL;
+	}
+	oldname = argv[optind++];
+	newname = argv[optind++];
+
+	if (strlen(newname) != strlen(oldname)) {
+		fprintf(stderr, "New filename must have the same length as the old one\n");
+		return -EINVAL;
+	}
+
+	for (offset = info->bootfs_offset; ; offset += (je32_to_cpu(node.totlen) + 0x03) & ~0x03) {
+		char name[FILENAME_MAX];
+		uint32_t crc32;
+
+		if (fseek(fp, offset, SEEK_SET)) {
+			err = -errno;
+			fprintf(stderr, "Failed to fseek: %d\n", err);
+			return err;
+		}
+
+		bytes = fread(&node, 1, sizeof(node), fp);
+		if (bytes != sizeof(node)) {
+			fprintf(stderr, "Failed to read %zu bytes\n", sizeof(node));
+			return -EIO;
+		}
+
+		if (je16_to_cpu(node.magic) != JFFS2_MAGIC_BITMASK) {
+			break;
+		}
+
+		if (je16_to_cpu(node.nodetype) != JFFS2_NODETYPE_DIRENT) {
+			continue;
+		}
+
+		bytes += fread((uint8_t *)&dirent + sizeof(node), 1, sizeof(dirent) - sizeof(node), fp);
+		if (bytes != sizeof(dirent)) {
+			fprintf(stderr, "Failed to read %zu bytes\n", sizeof(node));
+			return -EIO;
+		}
+
+		if (dirent.nsize + 1 > sizeof(name)) {
+			fprintf(stderr, "Too long filename\n");
+			err = -ENOMEM;
+			continue;
+		}
+
+		bytes = fread(name, 1, dirent.nsize, fp);
+		if (bytes != dirent.nsize) {
+			fprintf(stderr, "Failed to read filename\n");
+			return -EIO;
+		}
+		name[bytes] = '\0';
+
+		if (debug)
+			printf("offset:%08zx name_crc:%04x filename:%s\n", offset, je32_to_cpu(dirent.name_crc), name);
+
+		if (strcmp(name, oldname)) {
+			continue;
+		}
+
+		if (fseek(fp, offset + offsetof(struct jffs2_raw_dirent, name_crc), SEEK_SET)) {
+			err = -errno;
+			fprintf(stderr, "Failed to fseek: %d\n", err);
+			return err;
+		}
+		crc32 = bcm4908img_crc32(0, newname, dirent.nsize);
+		bytes = fwrite(&crc32, 1, sizeof(crc32), fp);
+		if (bytes != sizeof(crc32)) {
+			fprintf(stderr, "Failed to write new CRC32\n");
+			return -EIO;
+		}
+
+		if (fseek(fp, offset + offsetof(struct jffs2_raw_dirent, name), SEEK_SET)) {
+			err = -errno;
+			fprintf(stderr, "Failed to fseek: %d\n", err);
+			return err;
+		}
+		bytes = fwrite(newname, 1, dirent.nsize, fp);
+		if (bytes != dirent.nsize) {
+			fprintf(stderr, "Failed to write new filename\n");
+			return -EIO;
+		}
+
+		/* Calculate new BCM4908 image checksum */
+
+		err = bcm4908img_calc_crc32(fp, info);
+		if (err) {
+			fprintf(stderr, "Failed to write new filename\n");
+			return err;
+		}
+
+		info->tail.crc32 = cpu_to_le32(info->crc32);
+		if (fseek(fp, -sizeof(struct bcm4908img_tail), SEEK_END)) {
+			err = -errno;
+			fprintf(stderr, "Failed to write new filename\n");
+			return err;
+		}
+
+		if (fwrite(&info->tail, 1, sizeof(struct bcm4908img_tail), fp) != sizeof(struct bcm4908img_tail)) {
+			fprintf(stderr, "Failed to write updated tail\n");
+			return -EIO;
+		}
+
+		printf("Successfully renamed %s to the %s\n", oldname, newname);
+
+		return 0;
+	}
+
+	fprintf(stderr, "Failed to find %s\n", oldname);
+
+	return -ENOENT;
+}
+
+static int bcm4908img_bootfs(int argc, char **argv) {
+	struct bcm4908img_info info;
+	const char *pathname = NULL;
+	const char *mode;
+	const char *cmd;
+	FILE *fp;
+	int c;
+	int err = 0;
+
+	while ((c = getopt(argc, argv, "i:")) != -1) {
+		switch (c) {
+		case 'i':
+			pathname = optarg;
+			break;
+		}
+	}
+
+	if (argc - optind < 1) {
+		fprintf(stderr, "No bootfs command specified\n");
+		err = -EINVAL;
+		goto out;
+	}
+	cmd = argv[optind++];
+
+	mode = strcmp(cmd, "mv") ? "r" : "r+";
+	fp = bcm4908img_open(pathname, mode);
+	if (!fp) {
+		fprintf(stderr, "Failed to open BCM4908 image\n");
+		err = -EACCES;
+		goto out;
+	}
+
+	err = bcm4908img_parse(fp, &info);
+	if (err) {
+		fprintf(stderr, "Failed to parse BCM4908 image\n");
+		goto err_close;
+	}
+
+	if (!strcmp(cmd, "ls")) {
+		err = bcm4908img_bootfs_ls(fp, &info);
+	} else if (!strcmp(cmd, "mv")) {
+		err = bcm4908img_bootfs_mv(fp, &info, argc, argv);
+	} else {
+		err = -EINVAL;
+		fprintf(stderr, "Unsupported bootfs command: %s\n", cmd);
+	}
+
+err_close:
+	bcm4908img_close(fp);
+out:
+	return err;
+}
+
+/**************************************************
+ * Start
+ **************************************************/
+
+static void usage() {
+	printf("Usage:\n");
+	printf("\n");
+	printf("Info about a BCM4908 image:\n");
+	printf("\tbcm4908img info <options>\n");
+	printf("\t-i <file>\t\t\t\tinput BCM490 image\n");
+	printf("\n");
+	printf("Creating a new BCM4908 image:\n");
+	printf("\tbcm4908img create <file> [options]\n");
+	printf("\t-f file\t\t\t\tadd data from specified file\n");
+	printf("\t-a alignment\t\t\tpad image with zeros to specified alignment\n");
+	printf("\t-A offset\t\t\t\tappend zeros until reaching specified offset\n");
+	printf("\n");
+	printf("Extracting from a BCM4908 image:\n");
+	printf("\tbcm4908img extract <options>\n");
+	printf("\t-i <file>\t\t\t\tinput BCM490 image\n");
+	printf("\t-t <type>\t\t\t\tone of: cferom, bootfs, rootfs, firmware\n");
+	printf("\n");
+	printf("Access bootfs in a BCM4908 image:\n");
+	printf("\tbcm4908img bootfs <options> <command> <arguments>\n");
+	printf("\t-i <file>\t\t\t\tinput BCM490 image\n");
+	printf("\tls\t\t\t\t\tlist bootfs files\n");
+	printf("\tmv <source> <dest>\t\t\trename bootfs file\n");
+}
+
+int main(int argc, char **argv) {
+	if (argc > 1) {
+		optind++;
+		if (!strcmp(argv[1], "info"))
+			return bcm4908img_info(argc, argv);
+		else if (!strcmp(argv[1], "create"))
+			return bcm4908img_create(argc, argv);
+		else if (!strcmp(argv[1], "extract"))
+			return bcm4908img_extract(argc, argv);
+		else if (!strcmp(argv[1], "bootfs"))
+			return bcm4908img_bootfs(argc, argv);
+	}
+
+	usage();
+	return 0;
+}
diff --git a/package/utils/bsdiff/Makefile b/package/utils/bsdiff/Makefile
new file mode 100644
index 0000000..d86be2d
--- /dev/null
+++ b/package/utils/bsdiff/Makefile
@@ -0,0 +1,80 @@
+#
+# Copyright (C) 2016 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=bsdiff
+PKG_VERSION:=4.3
+PKG_RELEASE:=2
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://www.daemonology.net/bsdiff/
+PKG_HASH:=18821588b2dc5bf159aa37d3bcb7b885d85ffd1e19f23a0c57a58723fea85f48
+PKG_MAINTAINER:=Hauke Mehrtens <hauke@hauke-m.de>
+HOST_BUILD_DEPENDS:=bzip2/host
+
+PKG_LICENSE:=BSD-2-Clause
+PKG_CPE_ID:=cpe:/a:daemonology:bsdiff
+
+include $(INCLUDE_DIR)/host-build.mk
+include $(INCLUDE_DIR)/package.mk
+
+define Package/bsdiff
+  SECTION:=utils
+  CATEGORY:=Utilities
+  DEPENDS:=+libbz2
+  TITLE:=Binary diff tool
+  URL:=https://www.daemonology.net/bsdiff/
+endef
+
+define Package/bspatch
+  SECTION:=utils
+  CATEGORY:=Utilities
+  DEPENDS:=+libbz2
+  TITLE:=Binary patch tool
+  URL:=https://www.daemonology.net/bsdiff/
+endef
+
+
+define Build/Compile
+	$(TARGET_CC) $(TARGET_CFLAGS) $(TARGET_CPPFLAGS) $(TARGET_LDFLAGS) \
+		-o $(PKG_BUILD_DIR)/bsdiff \
+		$(PKG_BUILD_DIR)/bsdiff.c -lbz2
+	$(TARGET_CC) $(TARGET_CFLAGS) $(TARGET_CPPFLAGS) $(TARGET_LDFLAGS) \
+		-o $(PKG_BUILD_DIR)/bspatch \
+		$(PKG_BUILD_DIR)/bspatch.c -lbz2
+endef
+
+define Package/bsdiff/install
+	$(INSTALL_DIR) $(1)/usr/bin/
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/bsdiff $(1)/usr/bin/bsdiff
+endef
+
+define Package/bspatch/install
+	$(INSTALL_DIR) $(1)/usr/bin/
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/bspatch $(1)/usr/bin/bspatch
+endef
+
+define Host/Install
+	$(INSTALL_DIR) $(STAGING_DIR_HOSTPKG)/bin/
+	$(MAKE) -C $(HOST_BUILD_DIR) PREFIX=$(STAGING_DIR_HOSTPKG)/ install
+endef
+
+define Host/Compile
+	$(HOSTCC) $(HOST_CFLAGS) $(HOST_LDFLAGS) \
+		-o $(HOST_BUILD_DIR)/bsdiff \
+		$(HOST_BUILD_DIR)/bsdiff.c -lbz2
+endef
+
+define Host/Install
+	$(INSTALL_BIN) $(HOST_BUILD_DIR)/bsdiff $(STAGING_DIR_HOSTPKG)/bin/
+endef
+
+$(eval $(call HostBuild))
+
+$(eval $(call BuildPackage,bsdiff))
+$(eval $(call BuildPackage,bspatch))
diff --git a/package/utils/bsdiff/patches/001-musl.patch b/package/utils/bsdiff/patches/001-musl.patch
new file mode 100644
index 0000000..1eeb114
--- /dev/null
+++ b/package/utils/bsdiff/patches/001-musl.patch
@@ -0,0 +1,84 @@
+--- a/bsdiff.c
++++ b/bsdiff.c
+@@ -101,7 +101,7 @@ static void split(off_t *I,off_t *V,off_
+ 	if(start+len>kk) split(I,V,kk,start+len-kk,h);
+ }
+ 
+-static void qsufsort(off_t *I,off_t *V,u_char *old,off_t oldsize)
++static void qsufsort(off_t *I,off_t *V,unsigned char *old,off_t oldsize)
+ {
+ 	off_t buckets[256];
+ 	off_t i,h,len;
+@@ -139,7 +139,7 @@ static void qsufsort(off_t *I,off_t *V,u
+ 	for(i=0;i<oldsize+1;i++) I[V[i]]=i;
+ }
+ 
+-static off_t matchlen(u_char *old,off_t oldsize,u_char *new,off_t newsize)
++static off_t matchlen(unsigned char *old,off_t oldsize,unsigned char *new,off_t newsize)
+ {
+ 	off_t i;
+ 
+@@ -149,8 +149,8 @@ static off_t matchlen(u_char *old,off_t
+ 	return i;
+ }
+ 
+-static off_t search(off_t *I,u_char *old,off_t oldsize,
+-		u_char *new,off_t newsize,off_t st,off_t en,off_t *pos)
++static off_t search(off_t *I,unsigned char *old,off_t oldsize,
++		unsigned char *new,off_t newsize,off_t st,off_t en,off_t *pos)
+ {
+ 	off_t x,y;
+ 
+@@ -175,7 +175,7 @@ static off_t search(off_t *I,u_char *old
+ 	};
+ }
+ 
+-static void offtout(off_t x,u_char *buf)
++static void offtout(off_t x,unsigned char *buf)
+ {
+ 	off_t y;
+ 
+@@ -196,7 +196,7 @@ static void offtout(off_t x,u_char *buf)
+ int main(int argc,char *argv[])
+ {
+ 	int fd;
+-	u_char *old,*new;
++	unsigned char *old,*new;
+ 	off_t oldsize,newsize;
+ 	off_t *I,*V;
+ 	off_t scan,pos,len;
+@@ -206,9 +206,9 @@ int main(int argc,char *argv[])
+ 	off_t overlap,Ss,lens;
+ 	off_t i;
+ 	off_t dblen,eblen;
+-	u_char *db,*eb;
+-	u_char buf[8];
+-	u_char header[32];
++	unsigned char *db,*eb;
++	unsigned char buf[8];
++	unsigned char header[32];
+ 	FILE * pf;
+ 	BZFILE * pfbz2;
+ 	int bz2err;
+--- a/bspatch.c
++++ b/bspatch.c
+@@ -36,7 +36,7 @@ __FBSDID("$FreeBSD: src/usr.bin/bsdiff/b
+ #include <unistd.h>
+ #include <fcntl.h>
+ 
+-static off_t offtin(u_char *buf)
++static off_t offtin(unsigned char *buf)
+ {
+ 	off_t y;
+ 
+@@ -62,8 +62,8 @@ int main(int argc,char * argv[])
+ 	int fd;
+ 	ssize_t oldsize,newsize;
+ 	ssize_t bzctrllen,bzdatalen;
+-	u_char header[32],buf[8];
+-	u_char *old, *new;
++	unsigned char header[32],buf[8];
++	unsigned char *old, *new;
+ 	off_t oldpos,newpos;
+ 	off_t ctrl[3];
+ 	off_t lenread;
diff --git a/package/utils/bsdiff/patches/020-CVE-2014-9862.patch b/package/utils/bsdiff/patches/020-CVE-2014-9862.patch
new file mode 100644
index 0000000..98a4931
--- /dev/null
+++ b/package/utils/bsdiff/patches/020-CVE-2014-9862.patch
@@ -0,0 +1,37 @@
+From: The FreeBSD Project
+Bug: https://security-tracker.debian.org/tracker/CVE-2014-9862
+Subject: CVE-2014-9862 - check for a negative value on numbers of bytes
+  The implementation of bspatch does not check for a negative value on numbers
+  of bytes read from the diff and extra streams, allowing an attacker who
+  can control the patch file to write at arbitrary locations in the heap.
+  .
+  bspatch's main loop reads three numbers from the "control" stream in
+  the patch: X, Y and Z. The first two are the number of bytes to read
+  from "diff" and "extra" (and thus only non-negative), while the
+  third one could be positive or negative and moves the oldpos pointer
+  on the source image. These 3 values are 64bits signed ints (encoded
+  somehow on the file) that are later passed the function that reads
+  from the streams, but those values are not verified to be
+  non-negative.
+  .
+  Official report https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-9862
+  The patch was downloaded from a link pointed by
+  https://security.freebsd.org/advisories/FreeBSD-SA-16:25.bsp
+
+---
+ bspatch.c |    4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/bspatch.c
++++ b/bspatch.c
+@@ -152,6 +152,10 @@ int main(int argc,char * argv[])
+ 		};
+ 
+ 		/* Sanity-check */
++		if ((ctrl[0] < 0) || (ctrl[1] < 0))
++			errx(1,"Corrupt patch\n");
++
++		/* Sanity-check */
+ 		if(newpos+ctrl[0]>newsize)
+ 			errx(1,"Corrupt patch\n");
+ 
diff --git a/package/utils/bsdiff/patches/033-CVE-2020-14315.patch b/package/utils/bsdiff/patches/033-CVE-2020-14315.patch
new file mode 100644
index 0000000..975cb18
--- /dev/null
+++ b/package/utils/bsdiff/patches/033-CVE-2020-14315.patch
@@ -0,0 +1,383 @@
+Description: patch for CVE-2020-14315
+ A memory corruption vulnerability is present in bspatch as shipped in
+ Colin Percival’s bsdiff tools version 4.3. Insufficient checks when
+ handling external inputs allows an attacker to bypass the sanity checks
+ in place and write out of a dynamically allocated buffer boundaries.
+Source: https://svnweb.freebsd.org/base/head/usr.bin/bsdiff/bspatch/bspatch.c?revision=352742&view=co
+Author: tony mancill <tmancill@debian.org>
+Comment: The patch was created by comparing the Debian sources to the
+ "Confirmed Patched Version" [1] documented in the
+ X41 D-SEC GmbH Security Advisory: X41-2020-006 [2].
+ References to FreeBSD capsicum have been dropped.  Definitions for
+ TYPE_MINIMUM and TYPE_MAXIMUM have been borrowed from the Debian
+ coreutils package sources but originate in gnulib [3] and are used to
+ define OFF_MIN and OFF_MAX (limits of off_t). Whitespace changes from
+ the confirmed patched version are also included and keep the difference
+ between the Debian sources and the confirmed patched version minimal.
+ .
+ [1] https://svnweb.freebsd.org/base/head/usr.bin/bsdiff/bspatch/bspatch.c?revision=352742&view=co
+ [2] https://www.openwall.com/lists/oss-security/2020/07/09/2
+ [3] https://www.gnu.org/software/gnulib/
+Last-Update: 2021-04-03
+Forwarded: not-needed
+Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=964796
+
+--- a/bspatch.c
++++ b/bspatch.c
+@@ -1,4 +1,6 @@
+ /*-
++ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
++ *
+  * Copyright 2003-2005 Colin Percival
+  * All rights reserved
+  *
+@@ -25,55 +27,147 @@
+  */
+ 
+ #if 0
+-__FBSDID("$FreeBSD: src/usr.bin/bsdiff/bspatch/bspatch.c,v 1.1 2005/08/06 01:59:06 cperciva Exp $");
++__FBSDID("$FreeBSD$");
+ #endif
+ 
+ #include <bzlib.h>
+-#include <stdlib.h>
++#include <err.h>
++#include <fcntl.h>
++#include <libgen.h>
++#include <limits.h>
++#include <stdint.h>
+ #include <stdio.h>
++#include <stdlib.h>
+ #include <string.h>
+-#include <err.h>
+ #include <unistd.h>
+-#include <fcntl.h>
++
++#ifndef O_BINARY
++#define O_BINARY 0
++#endif
++#define HEADER_SIZE 32
++
++/* TYPE_MINIMUM and TYPE_MAXIMUM taken from coreutils */
++#ifndef TYPE_MINIMUM
++#define TYPE_MINIMUM(t) \
++  ((t) ((t) 0 < (t) -1 ? (t) 0 : ~ TYPE_MAXIMUM (t)))
++#endif
++#ifndef TYPE_MAXIMUM
++#define TYPE_MAXIMUM(t) \
++  ((t) ((t) 0 < (t) -1 \
++        ? (t) -1 \
++        : ((((t) 1 << (sizeof (t) * CHAR_BIT - 2)) - 1) * 2 + 1)))
++#endif
++
++#ifndef OFF_MAX
++#define OFF_MAX TYPE_MAXIMUM(off_t)
++#endif
++
++#ifndef OFF_MIN
++#define OFF_MIN TYPE_MINIMUM(off_t)
++#endif
++
++static char *newfile;
++static int dirfd = -1;
++
++static void
++exit_cleanup(void)
++{
++
++	if (dirfd != -1 && newfile != NULL)
++		if (unlinkat(dirfd, newfile, 0))
++			warn("unlinkat");
++}
++
++static inline off_t
++add_off_t(off_t a, off_t b)
++{
++	off_t result;
++
++#if __GNUC__ >= 5 || \
++    (defined(__has_builtin) && __has_builtin(__builtin_add_overflow))
++	if (__builtin_add_overflow(a, b, &result))
++		errx(1, "Corrupt patch");
++#else
++	if ((b > 0 && a > OFF_MAX - b) || (b < 0 && a < OFF_MIN - b))
++		errx(1, "Corrupt patch");
++	result = a + b;
++#endif
++	return result;
++}
+ 
+ static off_t offtin(unsigned char *buf)
+ {
+ 	off_t y;
+ 
+-	y=buf[7]&0x7F;
+-	y=y*256;y+=buf[6];
+-	y=y*256;y+=buf[5];
+-	y=y*256;y+=buf[4];
+-	y=y*256;y+=buf[3];
+-	y=y*256;y+=buf[2];
+-	y=y*256;y+=buf[1];
+-	y=y*256;y+=buf[0];
++	y = buf[7] & 0x7F;
++	y = y * 256; y += buf[6];
++	y = y * 256; y += buf[5];
++	y = y * 256; y += buf[4];
++	y = y * 256; y += buf[3];
++	y = y * 256; y += buf[2];
++	y = y * 256; y += buf[1];
++	y = y * 256; y += buf[0];
+ 
+-	if(buf[7]&0x80) y=-y;
++	if (buf[7] & 0x80)
++		y = -y;
+ 
+-	return y;
++	return (y);
+ }
+ 
+-int main(int argc,char * argv[])
++static void
++usage(void)
+ {
+-	FILE * f, * cpf, * dpf, * epf;
+-	BZFILE * cpfbz2, * dpfbz2, * epfbz2;
++
++	fprintf(stderr, "usage: bspatch oldfile newfile patchfile\n");
++	exit(1);
++}
++
++int main(int argc, char *argv[])
++{
++	FILE *f, *cpf, *dpf, *epf;
++	BZFILE *cpfbz2, *dpfbz2, *epfbz2;
++	char *directory, *namebuf;
+ 	int cbz2err, dbz2err, ebz2err;
+-	int fd;
+-	ssize_t oldsize,newsize;
+-	ssize_t bzctrllen,bzdatalen;
+-	unsigned char header[32],buf[8];
++	int newfd, oldfd;
++	off_t oldsize, newsize;
++	off_t bzctrllen, bzdatalen;
++	unsigned char header[HEADER_SIZE], buf[8];
+ 	unsigned char *old, *new;
+-	off_t oldpos,newpos;
++	off_t oldpos, newpos;
+ 	off_t ctrl[3];
+-	off_t lenread;
+-	off_t i;
++	off_t i, lenread, offset;
+ 
+-	if(argc!=4) errx(1,"usage: %s oldfile newfile patchfile\n",argv[0]);
++	if (argc != 4)
++		usage();
+ 
+ 	/* Open patch file */
+-	if ((f = fopen(argv[3], "r")) == NULL)
++	if ((f = fopen(argv[3], "rb")) == NULL)
++		err(1, "fopen(%s)", argv[3]);
++	/* Open patch file for control block */
++	if ((cpf = fopen(argv[3], "rb")) == NULL)
++		err(1, "fopen(%s)", argv[3]);
++	/* open patch file for diff block */
++	if ((dpf = fopen(argv[3], "rb")) == NULL)
+ 		err(1, "fopen(%s)", argv[3]);
++	/* open patch file for extra block */
++	if ((epf = fopen(argv[3], "rb")) == NULL)
++		err(1, "fopen(%s)", argv[3]);
++	/* open oldfile */
++	if ((oldfd = open(argv[1], O_RDONLY | O_BINARY, 0)) < 0)
++		err(1, "open(%s)", argv[1]);
++	/* open directory where we'll write newfile */
++	if ((namebuf = strdup(argv[2])) == NULL ||
++	    (directory = dirname(namebuf)) == NULL ||
++	    (dirfd = open(directory, O_DIRECTORY)) < 0)
++		err(1, "open %s", argv[2]);
++	free(namebuf);
++	if ((newfile = basename(argv[2])) == NULL)
++		err(1, "basename");
++	/* open newfile */
++	if ((newfd = openat(dirfd, newfile,
++	    O_CREAT | O_TRUNC | O_WRONLY | O_BINARY, 0666)) < 0)
++		err(1, "open(%s)", argv[2]);
++	atexit(exit_cleanup);
+ 
+ 	/*
+ 	File format:
+@@ -90,104 +184,104 @@ int main(int argc,char * argv[])
+ 	*/
+ 
+ 	/* Read header */
+-	if (fread(header, 1, 32, f) < 32) {
++	if (fread(header, 1, HEADER_SIZE, f) < HEADER_SIZE) {
+ 		if (feof(f))
+-			errx(1, "Corrupt patch\n");
++			errx(1, "Corrupt patch");
+ 		err(1, "fread(%s)", argv[3]);
+ 	}
+ 
+ 	/* Check for appropriate magic */
+ 	if (memcmp(header, "BSDIFF40", 8) != 0)
+-		errx(1, "Corrupt patch\n");
++		errx(1, "Corrupt patch");
+ 
+ 	/* Read lengths from header */
+-	bzctrllen=offtin(header+8);
+-	bzdatalen=offtin(header+16);
+-	newsize=offtin(header+24);
+-	if((bzctrllen<0) || (bzdatalen<0) || (newsize<0))
+-		errx(1,"Corrupt patch\n");
++	bzctrllen = offtin(header + 8);
++	bzdatalen = offtin(header + 16);
++	newsize = offtin(header + 24);
++	if (bzctrllen < 0 || bzctrllen > OFF_MAX - HEADER_SIZE ||
++	    bzdatalen < 0 || bzctrllen + HEADER_SIZE > OFF_MAX - bzdatalen ||
++	    newsize < 0 || newsize > SSIZE_MAX)
++		errx(1, "Corrupt patch");
+ 
+ 	/* Close patch file and re-open it via libbzip2 at the right places */
+ 	if (fclose(f))
+ 		err(1, "fclose(%s)", argv[3]);
+-	if ((cpf = fopen(argv[3], "r")) == NULL)
+-		err(1, "fopen(%s)", argv[3]);
+-	if (fseeko(cpf, 32, SEEK_SET))
+-		err(1, "fseeko(%s, %lld)", argv[3],
+-		    (long long)32);
++	offset = HEADER_SIZE;
++	if (fseeko(cpf, offset, SEEK_SET))
++		err(1, "fseeko(%s, %jd)", argv[3], (intmax_t)offset);
+ 	if ((cpfbz2 = BZ2_bzReadOpen(&cbz2err, cpf, 0, 0, NULL, 0)) == NULL)
+ 		errx(1, "BZ2_bzReadOpen, bz2err = %d", cbz2err);
+-	if ((dpf = fopen(argv[3], "r")) == NULL)
+-		err(1, "fopen(%s)", argv[3]);
+-	if (fseeko(dpf, 32 + bzctrllen, SEEK_SET))
+-		err(1, "fseeko(%s, %lld)", argv[3],
+-		    (long long)(32 + bzctrllen));
++	offset = add_off_t(offset, bzctrllen);
++	if (fseeko(dpf, offset, SEEK_SET))
++		err(1, "fseeko(%s, %jd)", argv[3], (intmax_t)offset);
+ 	if ((dpfbz2 = BZ2_bzReadOpen(&dbz2err, dpf, 0, 0, NULL, 0)) == NULL)
+ 		errx(1, "BZ2_bzReadOpen, bz2err = %d", dbz2err);
+-	if ((epf = fopen(argv[3], "r")) == NULL)
+-		err(1, "fopen(%s)", argv[3]);
+-	if (fseeko(epf, 32 + bzctrllen + bzdatalen, SEEK_SET))
+-		err(1, "fseeko(%s, %lld)", argv[3],
+-		    (long long)(32 + bzctrllen + bzdatalen));
++	offset = add_off_t(offset, bzdatalen);
++	if (fseeko(epf, offset, SEEK_SET))
++		err(1, "fseeko(%s, %jd)", argv[3], (intmax_t)offset);
+ 	if ((epfbz2 = BZ2_bzReadOpen(&ebz2err, epf, 0, 0, NULL, 0)) == NULL)
+ 		errx(1, "BZ2_bzReadOpen, bz2err = %d", ebz2err);
+ 
+-	if(((fd=open(argv[1],O_RDONLY,0))<0) ||
+-		((oldsize=lseek(fd,0,SEEK_END))==-1) ||
+-		((old=malloc(oldsize+1))==NULL) ||
+-		(lseek(fd,0,SEEK_SET)!=0) ||
+-		(read(fd,old,oldsize)!=oldsize) ||
+-		(close(fd)==-1)) err(1,"%s",argv[1]);
+-	if((new=malloc(newsize+1))==NULL) err(1,NULL);
+-
+-	oldpos=0;newpos=0;
+-	while(newpos<newsize) {
++	if ((oldsize = lseek(oldfd, 0, SEEK_END)) == -1 ||
++	    oldsize > SSIZE_MAX ||
++	    (old = malloc(oldsize)) == NULL ||
++	    lseek(oldfd, 0, SEEK_SET) != 0 ||
++	    read(oldfd, old, oldsize) != oldsize ||
++	    close(oldfd) == -1)
++		err(1, "%s", argv[1]);
++	if ((new = malloc(newsize)) == NULL)
++		err(1, NULL);
++
++	oldpos = 0;
++	newpos = 0;
++	while (newpos < newsize) {
+ 		/* Read control data */
+-		for(i=0;i<=2;i++) {
++		for (i = 0; i <= 2; i++) {
+ 			lenread = BZ2_bzRead(&cbz2err, cpfbz2, buf, 8);
+ 			if ((lenread < 8) || ((cbz2err != BZ_OK) &&
+ 			    (cbz2err != BZ_STREAM_END)))
+-				errx(1, "Corrupt patch\n");
+-			ctrl[i]=offtin(buf);
+-		};
++				errx(1, "Corrupt patch");
++			ctrl[i] = offtin(buf);
++		}
+ 
+ 		/* Sanity-check */
+-		if ((ctrl[0] < 0) || (ctrl[1] < 0))
+-			errx(1,"Corrupt patch\n");
++		if (ctrl[0] < 0 || ctrl[0] > INT_MAX ||
++		    ctrl[1] < 0 || ctrl[1] > INT_MAX)
++			errx(1, "Corrupt patch");
+ 
+ 		/* Sanity-check */
+-		if(newpos+ctrl[0]>newsize)
+-			errx(1,"Corrupt patch\n");
++		if (add_off_t(newpos, ctrl[0]) > newsize)
++			errx(1, "Corrupt patch");
+ 
+ 		/* Read diff string */
+ 		lenread = BZ2_bzRead(&dbz2err, dpfbz2, new + newpos, ctrl[0]);
+ 		if ((lenread < ctrl[0]) ||
+ 		    ((dbz2err != BZ_OK) && (dbz2err != BZ_STREAM_END)))
+-			errx(1, "Corrupt patch\n");
++			errx(1, "Corrupt patch");
+ 
+ 		/* Add old data to diff string */
+-		for(i=0;i<ctrl[0];i++)
+-			if((oldpos+i>=0) && (oldpos+i<oldsize))
+-				new[newpos+i]+=old[oldpos+i];
++		for (i = 0; i < ctrl[0]; i++)
++			if (add_off_t(oldpos, i) < oldsize)
++				new[newpos + i] += old[oldpos + i];
+ 
+ 		/* Adjust pointers */
+-		newpos+=ctrl[0];
+-		oldpos+=ctrl[0];
++		newpos = add_off_t(newpos, ctrl[0]);
++		oldpos = add_off_t(oldpos, ctrl[0]);
+ 
+ 		/* Sanity-check */
+-		if(newpos+ctrl[1]>newsize)
+-			errx(1,"Corrupt patch\n");
++		if (add_off_t(newpos, ctrl[1]) > newsize)
++			errx(1, "Corrupt patch");
+ 
+ 		/* Read extra string */
+ 		lenread = BZ2_bzRead(&ebz2err, epfbz2, new + newpos, ctrl[1]);
+ 		if ((lenread < ctrl[1]) ||
+ 		    ((ebz2err != BZ_OK) && (ebz2err != BZ_STREAM_END)))
+-			errx(1, "Corrupt patch\n");
++			errx(1, "Corrupt patch");
+ 
+ 		/* Adjust pointers */
+-		newpos+=ctrl[1];
+-		oldpos+=ctrl[2];
+-	};
++		newpos = add_off_t(newpos, ctrl[1]);
++		oldpos = add_off_t(oldpos, ctrl[2]);
++	}
+ 
+ 	/* Clean up the bzip2 reads */
+ 	BZ2_bzReadClose(&cbz2err, cpfbz2);
+@@ -197,12 +291,13 @@ int main(int argc,char * argv[])
+ 		err(1, "fclose(%s)", argv[3]);
+ 
+ 	/* Write the new file */
+-	if(((fd=open(argv[2],O_CREAT|O_TRUNC|O_WRONLY,0666))<0) ||
+-		(write(fd,new,newsize)!=newsize) || (close(fd)==-1))
+-		err(1,"%s",argv[2]);
++	if (write(newfd, new, newsize) != newsize || close(newfd) == -1)
++		err(1, "%s", argv[2]);
++	/* Disable atexit cleanup */
++	newfile = NULL;
+ 
+ 	free(new);
+ 	free(old);
+ 
+-	return 0;
++	return (0);
+ }
diff --git a/package/utils/busybox/Config-defaults.in b/package/utils/busybox/Config-defaults.in
new file mode 100644
index 0000000..a471c4e
--- /dev/null
+++ b/package/utils/busybox/Config-defaults.in
@@ -0,0 +1,3242 @@
+config BUSYBOX_DEFAULT_HAVE_DOT_CONFIG
+	bool
+	default y
+config BUSYBOX_DEFAULT_DESKTOP
+	bool
+	default n
+config BUSYBOX_DEFAULT_EXTRA_COMPAT
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEDORA_COMPAT
+	bool
+	default n
+config BUSYBOX_DEFAULT_INCLUDE_SUSv2
+	bool
+	default y
+config BUSYBOX_DEFAULT_LONG_OPTS
+	bool
+	default y
+config BUSYBOX_DEFAULT_SHOW_USAGE
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_VERBOSE_USAGE
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_COMPRESS_USAGE
+	bool
+	default n
+config BUSYBOX_DEFAULT_LFS
+	bool
+	default y
+config BUSYBOX_DEFAULT_PAM
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_DEVPTS
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_UTMP
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_WTMP
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_PIDFILE
+	bool
+	default y
+config BUSYBOX_DEFAULT_PID_FILE_PATH
+	string
+	default "/var/run"
+config BUSYBOX_DEFAULT_BUSYBOX
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_SHOW_SCRIPT
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_INSTALLER
+	bool
+	default n
+config BUSYBOX_DEFAULT_INSTALL_NO_USR
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_SUID
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_SUID_CONFIG
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_SUID_CONFIG_QUIET
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_PREFER_APPLETS
+	bool
+	default y
+config BUSYBOX_DEFAULT_BUSYBOX_EXEC_PATH
+	string
+	default "/proc/self/exe"
+config BUSYBOX_DEFAULT_SELINUX
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_CLEAN_UP
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_SYSLOG_INFO
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_SYSLOG
+	bool
+	default y
+config BUSYBOX_DEFAULT_STATIC
+	bool
+	default n
+config BUSYBOX_DEFAULT_PIE
+	bool
+	default n
+config BUSYBOX_DEFAULT_NOMMU
+	bool
+	default n
+config BUSYBOX_DEFAULT_BUILD_LIBBUSYBOX
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_LIBBUSYBOX_STATIC
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_INDIVIDUAL
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_SHARED_BUSYBOX
+	bool
+	default n
+config BUSYBOX_DEFAULT_CROSS_COMPILER_PREFIX
+	string
+	default ""
+config BUSYBOX_DEFAULT_SYSROOT
+	string
+	default ""
+config BUSYBOX_DEFAULT_EXTRA_CFLAGS
+	string
+	default ""
+config BUSYBOX_DEFAULT_EXTRA_LDFLAGS
+	string
+	default ""
+config BUSYBOX_DEFAULT_EXTRA_LDLIBS
+	string
+	default ""
+config BUSYBOX_DEFAULT_USE_PORTABLE_CODE
+	bool
+	default n
+config BUSYBOX_DEFAULT_STACK_OPTIMIZATION_386
+	bool
+	default n
+config BUSYBOX_DEFAULT_STATIC_LIBGCC
+	bool
+	default n
+config BUSYBOX_DEFAULT_INSTALL_APPLET_SYMLINKS
+	bool
+	default y
+config BUSYBOX_DEFAULT_INSTALL_APPLET_HARDLINKS
+	bool
+	default n
+config BUSYBOX_DEFAULT_INSTALL_APPLET_SCRIPT_WRAPPERS
+	bool
+	default n
+config BUSYBOX_DEFAULT_INSTALL_APPLET_DONT
+	bool
+	default n
+config BUSYBOX_DEFAULT_INSTALL_SH_APPLET_SYMLINK
+	bool
+	default n
+config BUSYBOX_DEFAULT_INSTALL_SH_APPLET_HARDLINK
+	bool
+	default n
+config BUSYBOX_DEFAULT_INSTALL_SH_APPLET_SCRIPT_WRAPPER
+	bool
+	default n
+config BUSYBOX_DEFAULT_PREFIX
+	string
+	default "./_install"
+config BUSYBOX_DEFAULT_DEBUG
+	bool
+	default n
+config BUSYBOX_DEFAULT_DEBUG_PESSIMIZE
+	bool
+	default n
+config BUSYBOX_DEFAULT_DEBUG_SANITIZE
+	bool
+	default n
+config BUSYBOX_DEFAULT_UNIT_TEST
+	bool
+	default n
+config BUSYBOX_DEFAULT_WERROR
+	bool
+	default n
+config BUSYBOX_DEFAULT_WARN_SIMPLE_MSG
+	bool
+	default n
+config BUSYBOX_DEFAULT_NO_DEBUG_LIB
+	bool
+	default y
+config BUSYBOX_DEFAULT_DMALLOC
+	bool
+	default n
+config BUSYBOX_DEFAULT_EFENCE
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_USE_BSS_TAIL
+	bool
+	default n
+config BUSYBOX_DEFAULT_FLOAT_DURATION
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_RTMINMAX
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_RTMINMAX_USE_LIBC_DEFINITIONS
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_BUFFERS_USE_MALLOC
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_BUFFERS_GO_ON_STACK
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_BUFFERS_GO_IN_BSS
+	bool
+	default n
+config BUSYBOX_DEFAULT_PASSWORD_MINLEN
+	int
+	default 6
+config BUSYBOX_DEFAULT_MD5_SMALL
+	int
+	default 1
+config BUSYBOX_DEFAULT_SHA1_SMALL
+	int
+	default 3
+config BUSYBOX_DEFAULT_SHA1_HWACCEL
+	bool
+	default y
+config BUSYBOX_DEFAULT_SHA256_HWACCEL
+	bool
+	default y
+config BUSYBOX_DEFAULT_SHA3_SMALL
+	int
+	default 1
+config BUSYBOX_DEFAULT_FEATURE_NON_POSIX_CP
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_VERBOSE_CP_MESSAGE
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_USE_SENDFILE
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_COPYBUF_KB
+	int
+	default 4
+config BUSYBOX_DEFAULT_MONOTONIC_SYSCALL
+	bool
+	default y
+config BUSYBOX_DEFAULT_IOCTL_HEX2STR_ERROR
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_EDITING
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_EDITING_MAX_LEN
+	int
+	default 512
+config BUSYBOX_DEFAULT_FEATURE_EDITING_VI
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_EDITING_HISTORY
+	int
+	default 256
+config BUSYBOX_DEFAULT_FEATURE_EDITING_SAVEHISTORY
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_EDITING_SAVE_ON_EXIT
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_REVERSE_SEARCH
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_TAB_COMPLETION
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_USERNAME_COMPLETION
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_EDITING_FANCY_PROMPT
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_EDITING_WINCH
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_EDITING_ASK_TERMINAL
+	bool
+	default n
+config BUSYBOX_DEFAULT_LOCALE_SUPPORT
+	bool
+	default n
+config BUSYBOX_DEFAULT_UNICODE_SUPPORT
+	bool
+	default n
+config BUSYBOX_DEFAULT_UNICODE_USING_LOCALE
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_CHECK_UNICODE_IN_ENV
+	bool
+	default n
+config BUSYBOX_DEFAULT_SUBST_WCHAR
+	int
+	default 0
+config BUSYBOX_DEFAULT_LAST_SUPPORTED_WCHAR
+	int
+	default 0
+config BUSYBOX_DEFAULT_UNICODE_COMBINING_WCHARS
+	bool
+	default n
+config BUSYBOX_DEFAULT_UNICODE_WIDE_WCHARS
+	bool
+	default n
+config BUSYBOX_DEFAULT_UNICODE_BIDI_SUPPORT
+	bool
+	default n
+config BUSYBOX_DEFAULT_UNICODE_NEUTRAL_TABLE
+	bool
+	default n
+config BUSYBOX_DEFAULT_UNICODE_PRESERVE_BROKEN
+	bool
+	default n
+config BUSYBOX_DEFAULT_LOOP_CONFIGURE
+	bool
+	default n
+config BUSYBOX_DEFAULT_NO_LOOP_CONFIGURE
+	bool
+	default n
+config BUSYBOX_DEFAULT_TRY_LOOP_CONFIGURE
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_SEAMLESS_XZ
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_SEAMLESS_LZMA
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_SEAMLESS_BZ2
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_SEAMLESS_GZ
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_SEAMLESS_Z
+	bool
+	default n
+config BUSYBOX_DEFAULT_AR
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_AR_LONG_FILENAMES
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_AR_CREATE
+	bool
+	default n
+config BUSYBOX_DEFAULT_UNCOMPRESS
+	bool
+	default n
+config BUSYBOX_DEFAULT_GUNZIP
+	bool
+	default y
+config BUSYBOX_DEFAULT_ZCAT
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_GUNZIP_LONG_OPTIONS
+	bool
+	default n
+config BUSYBOX_DEFAULT_BUNZIP2
+	bool
+	default n
+config BUSYBOX_DEFAULT_BZCAT
+	bool
+	default n
+config BUSYBOX_DEFAULT_UNLZMA
+	bool
+	default n
+config BUSYBOX_DEFAULT_LZCAT
+	bool
+	default n
+config BUSYBOX_DEFAULT_LZMA
+	bool
+	default n
+config BUSYBOX_DEFAULT_UNXZ
+	bool
+	default n
+config BUSYBOX_DEFAULT_XZCAT
+	bool
+	default n
+config BUSYBOX_DEFAULT_XZ
+	bool
+	default n
+config BUSYBOX_DEFAULT_BZIP2
+	bool
+	default n
+config BUSYBOX_DEFAULT_BZIP2_SMALL
+	int
+	default 0
+config BUSYBOX_DEFAULT_FEATURE_BZIP2_DECOMPRESS
+	bool
+	default n
+config BUSYBOX_DEFAULT_CPIO
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_CPIO_O
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_CPIO_P
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_CPIO_IGNORE_DEVNO
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_CPIO_RENUMBER_INODES
+	bool
+	default n
+config BUSYBOX_DEFAULT_DPKG
+	bool
+	default n
+config BUSYBOX_DEFAULT_DPKG_DEB
+	bool
+	default n
+config BUSYBOX_DEFAULT_GZIP
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_GZIP_LONG_OPTIONS
+	bool
+	default n
+config BUSYBOX_DEFAULT_GZIP_FAST
+	int
+	default 0
+config BUSYBOX_DEFAULT_FEATURE_GZIP_LEVELS
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_GZIP_DECOMPRESS
+	bool
+	default y
+config BUSYBOX_DEFAULT_LZOP
+	bool
+	default n
+config BUSYBOX_DEFAULT_UNLZOP
+	bool
+	default n
+config BUSYBOX_DEFAULT_LZOPCAT
+	bool
+	default n
+config BUSYBOX_DEFAULT_LZOP_COMPR_HIGH
+	bool
+	default n
+config BUSYBOX_DEFAULT_RPM
+	bool
+	default n
+config BUSYBOX_DEFAULT_RPM2CPIO
+	bool
+	default n
+config BUSYBOX_DEFAULT_TAR
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_TAR_LONG_OPTIONS
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_TAR_CREATE
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_TAR_AUTODETECT
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_TAR_FROM
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_TAR_OLDGNU_COMPATIBILITY
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_TAR_OLDSUN_COMPATIBILITY
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_TAR_GNU_EXTENSIONS
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_TAR_TO_COMMAND
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_TAR_UNAME_GNAME
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_TAR_NOPRESERVE_TIME
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_TAR_SELINUX
+	bool
+	default n
+config BUSYBOX_DEFAULT_UNZIP
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_UNZIP_CDF
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_UNZIP_BZIP2
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_UNZIP_LZMA
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_UNZIP_XZ
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_LZMA_FAST
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_VERBOSE
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_TIMEZONE
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_PRESERVE_HARDLINKS
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_HUMAN_READABLE
+	bool
+	default y
+config BUSYBOX_DEFAULT_BASENAME
+	bool
+	default y
+config BUSYBOX_DEFAULT_CAT
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_CATN
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_CATV
+	bool
+	default n
+config BUSYBOX_DEFAULT_CHGRP
+	bool
+	default y
+config BUSYBOX_DEFAULT_CHMOD
+	bool
+	default y
+config BUSYBOX_DEFAULT_CHOWN
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_CHOWN_LONG_OPTIONS
+	bool
+	default n
+config BUSYBOX_DEFAULT_CHROOT
+	bool
+	default y
+config BUSYBOX_DEFAULT_CKSUM
+	bool
+	default n
+config BUSYBOX_DEFAULT_CRC32
+	bool
+	default n
+config BUSYBOX_DEFAULT_COMM
+	bool
+	default n
+config BUSYBOX_DEFAULT_CP
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_CP_LONG_OPTIONS
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_CP_REFLINK
+	bool
+	default n
+config BUSYBOX_DEFAULT_CUT
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_CUT_REGEX
+	bool
+	default n
+config BUSYBOX_DEFAULT_DATE
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_DATE_ISOFMT
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_DATE_NANO
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_DATE_COMPAT
+	bool
+	default n
+config BUSYBOX_DEFAULT_DD
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_DD_SIGNAL_HANDLING
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_DD_THIRD_STATUS_LINE
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_DD_IBS_OBS
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_DD_STATUS
+	bool
+	default n
+config BUSYBOX_DEFAULT_DF
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_DF_FANCY
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_SKIP_ROOTFS
+	bool
+	default n
+config BUSYBOX_DEFAULT_DIRNAME
+	bool
+	default y
+config BUSYBOX_DEFAULT_DOS2UNIX
+	bool
+	default n
+config BUSYBOX_DEFAULT_UNIX2DOS
+	bool
+	default n
+config BUSYBOX_DEFAULT_DU
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_DU_DEFAULT_BLOCKSIZE_1K
+	bool
+	default y
+config BUSYBOX_DEFAULT_ECHO
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_FANCY_ECHO
+	bool
+	default y
+config BUSYBOX_DEFAULT_ENV
+	bool
+	default y
+config BUSYBOX_DEFAULT_EXPAND
+	bool
+	default n
+config BUSYBOX_DEFAULT_UNEXPAND
+	bool
+	default n
+config BUSYBOX_DEFAULT_EXPR
+	bool
+	default y
+config BUSYBOX_DEFAULT_EXPR_MATH_SUPPORT_64
+	bool
+	default y
+config BUSYBOX_DEFAULT_FACTOR
+	bool
+	default n
+config BUSYBOX_DEFAULT_FALSE
+	bool
+	default y
+config BUSYBOX_DEFAULT_FOLD
+	bool
+	default n
+config BUSYBOX_DEFAULT_HEAD
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_FANCY_HEAD
+	bool
+	default y
+config BUSYBOX_DEFAULT_HOSTID
+	bool
+	default n
+config BUSYBOX_DEFAULT_ID
+	bool
+	default y
+config BUSYBOX_DEFAULT_GROUPS
+	bool
+	default n
+config BUSYBOX_DEFAULT_INSTALL
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_INSTALL_LONG_OPTIONS
+	bool
+	default n
+config BUSYBOX_DEFAULT_LINK
+	bool
+	default n
+config BUSYBOX_DEFAULT_LN
+	bool
+	default y
+config BUSYBOX_DEFAULT_LOGNAME
+	bool
+	default n
+config BUSYBOX_DEFAULT_LS
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_LS_FILETYPES
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_LS_FOLLOWLINKS
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_LS_RECURSIVE
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_LS_WIDTH
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_LS_SORTFILES
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_LS_TIMESTAMPS
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_LS_USERNAME
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_LS_COLOR
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_LS_COLOR_IS_DEFAULT
+	bool
+	default y
+config BUSYBOX_DEFAULT_MD5SUM
+	bool
+	default y
+config BUSYBOX_DEFAULT_SHA1SUM
+	bool
+	default n
+config BUSYBOX_DEFAULT_SHA256SUM
+	bool
+	default y
+config BUSYBOX_DEFAULT_SHA512SUM
+	bool
+	default n
+config BUSYBOX_DEFAULT_SHA3SUM
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_MD5_SHA1_SUM_CHECK
+	bool
+	default y
+config BUSYBOX_DEFAULT_MKDIR
+	bool
+	default y
+config BUSYBOX_DEFAULT_MKFIFO
+	bool
+	default y
+config BUSYBOX_DEFAULT_MKNOD
+	bool
+	default y
+config BUSYBOX_DEFAULT_MKTEMP
+	bool
+	default y
+config BUSYBOX_DEFAULT_MV
+	bool
+	default y
+config BUSYBOX_DEFAULT_NICE
+	bool
+	default y
+config BUSYBOX_DEFAULT_NL
+	bool
+	default n
+config BUSYBOX_DEFAULT_NOHUP
+	bool
+	default n
+config BUSYBOX_DEFAULT_NPROC
+	bool
+	default n
+config BUSYBOX_DEFAULT_OD
+	bool
+	default n
+config BUSYBOX_DEFAULT_PASTE
+	bool
+	default n
+config BUSYBOX_DEFAULT_PRINTENV
+	bool
+	default n
+config BUSYBOX_DEFAULT_PRINTF
+	bool
+	default y
+config BUSYBOX_DEFAULT_PWD
+	bool
+	default y
+config BUSYBOX_DEFAULT_READLINK
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_READLINK_FOLLOW
+	bool
+	default y
+config BUSYBOX_DEFAULT_REALPATH
+	bool
+	default n
+config BUSYBOX_DEFAULT_RM
+	bool
+	default y
+config BUSYBOX_DEFAULT_RMDIR
+	bool
+	default y
+config BUSYBOX_DEFAULT_SEQ
+	bool
+	default y
+config BUSYBOX_DEFAULT_SHRED
+	bool
+	default n
+config BUSYBOX_DEFAULT_SHUF
+	bool
+	default n
+config BUSYBOX_DEFAULT_SLEEP
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_FANCY_SLEEP
+	bool
+	default y
+config BUSYBOX_DEFAULT_SORT
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_SORT_BIG
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_SORT_OPTIMIZE_MEMORY
+	bool
+	default n
+config BUSYBOX_DEFAULT_SPLIT
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_SPLIT_FANCY
+	bool
+	default n
+config BUSYBOX_DEFAULT_STAT
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_STAT_FORMAT
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_STAT_FILESYSTEM
+	bool
+	default n
+config BUSYBOX_DEFAULT_STTY
+	bool
+	default n
+config BUSYBOX_DEFAULT_SUM
+	bool
+	default n
+config BUSYBOX_DEFAULT_SYNC
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_SYNC_FANCY
+	bool
+	default n
+config BUSYBOX_DEFAULT_FSYNC
+	bool
+	default y
+config BUSYBOX_DEFAULT_TAC
+	bool
+	default n
+config BUSYBOX_DEFAULT_TAIL
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_FANCY_TAIL
+	bool
+	default y
+config BUSYBOX_DEFAULT_TEE
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_TEE_USE_BLOCK_IO
+	bool
+	default y
+config BUSYBOX_DEFAULT_TEST
+	bool
+	default y
+config BUSYBOX_DEFAULT_TEST1
+	bool
+	default y
+config BUSYBOX_DEFAULT_TEST2
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_TEST_64
+	bool
+	default y
+config BUSYBOX_DEFAULT_TIMEOUT
+	bool
+	default n
+config BUSYBOX_DEFAULT_TOUCH
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_TOUCH_SUSV3
+	bool
+	default y
+config BUSYBOX_DEFAULT_TR
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_TR_CLASSES
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_TR_EQUIV
+	bool
+	default n
+config BUSYBOX_DEFAULT_TRUE
+	bool
+	default y
+config BUSYBOX_DEFAULT_TRUNCATE
+	bool
+	default y if TARGET_bcm53xx
+	default n
+config BUSYBOX_DEFAULT_TSORT
+	bool
+	default n
+config BUSYBOX_DEFAULT_TTY
+	bool
+	default n
+config BUSYBOX_DEFAULT_UNAME
+	bool
+	default y
+config BUSYBOX_DEFAULT_UNAME_OSNAME
+	string
+	default "GNU/Linux"
+config BUSYBOX_DEFAULT_BB_ARCH
+	bool
+	default n
+config BUSYBOX_DEFAULT_UNIQ
+	bool
+	default y
+config BUSYBOX_DEFAULT_UNLINK
+	bool
+	default n
+config BUSYBOX_DEFAULT_USLEEP
+	bool
+	default n
+config BUSYBOX_DEFAULT_UUDECODE
+	bool
+	default n
+config BUSYBOX_DEFAULT_BASE32
+	bool
+	default n
+config BUSYBOX_DEFAULT_BASE64
+	bool
+	default n
+config BUSYBOX_DEFAULT_UUENCODE
+	bool
+	default n
+config BUSYBOX_DEFAULT_WC
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_WC_LARGE
+	bool
+	default n
+config BUSYBOX_DEFAULT_WHO
+	bool
+	default n
+config BUSYBOX_DEFAULT_W
+	bool
+	default n
+config BUSYBOX_DEFAULT_USERS
+	bool
+	default n
+config BUSYBOX_DEFAULT_WHOAMI
+	bool
+	default n
+config BUSYBOX_DEFAULT_YES
+	bool
+	default y
+config BUSYBOX_DEFAULT_CHVT
+	bool
+	default n
+config BUSYBOX_DEFAULT_CLEAR
+	bool
+	default y
+config BUSYBOX_DEFAULT_DEALLOCVT
+	bool
+	default n
+config BUSYBOX_DEFAULT_DUMPKMAP
+	bool
+	default n
+config BUSYBOX_DEFAULT_FGCONSOLE
+	bool
+	default n
+config BUSYBOX_DEFAULT_KBD_MODE
+	bool
+	default n
+config BUSYBOX_DEFAULT_LOADFONT
+	bool
+	default n
+config BUSYBOX_DEFAULT_SETFONT
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_SETFONT_TEXTUAL_MAP
+	bool
+	default n
+config BUSYBOX_DEFAULT_DEFAULT_SETFONT_DIR
+	string
+	default ""
+config BUSYBOX_DEFAULT_FEATURE_LOADFONT_PSF2
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_LOADFONT_RAW
+	bool
+	default n
+config BUSYBOX_DEFAULT_LOADKMAP
+	bool
+	default n
+config BUSYBOX_DEFAULT_OPENVT
+	bool
+	default n
+config BUSYBOX_DEFAULT_RESET
+	bool
+	default y
+config BUSYBOX_DEFAULT_RESIZE
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_RESIZE_PRINT
+	bool
+	default n
+config BUSYBOX_DEFAULT_SETCONSOLE
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_SETCONSOLE_LONG_OPTIONS
+	bool
+	default n
+config BUSYBOX_DEFAULT_SETKEYCODES
+	bool
+	default n
+config BUSYBOX_DEFAULT_SETLOGCONS
+	bool
+	default n
+config BUSYBOX_DEFAULT_SHOWKEY
+	bool
+	default n
+config BUSYBOX_DEFAULT_PIPE_PROGRESS
+	bool
+	default n
+config BUSYBOX_DEFAULT_RUN_PARTS
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_RUN_PARTS_LONG_OPTIONS
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_RUN_PARTS_FANCY
+	bool
+	default n
+config BUSYBOX_DEFAULT_START_STOP_DAEMON
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_START_STOP_DAEMON_LONG_OPTIONS
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_START_STOP_DAEMON_FANCY
+	bool
+	default n
+config BUSYBOX_DEFAULT_WHICH
+	bool
+	default y
+config BUSYBOX_DEFAULT_MINIPS
+	bool
+	default n
+config BUSYBOX_DEFAULT_NUKE
+	bool
+	default n
+config BUSYBOX_DEFAULT_RESUME
+	bool
+	default n
+config BUSYBOX_DEFAULT_RUN_INIT
+	bool
+	default n
+config BUSYBOX_DEFAULT_AWK
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_AWK_LIBM
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_AWK_GNU_EXTENSIONS
+	bool
+	default y
+config BUSYBOX_DEFAULT_CMP
+	bool
+	default y
+config BUSYBOX_DEFAULT_DIFF
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_DIFF_LONG_OPTIONS
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_DIFF_DIR
+	bool
+	default n
+config BUSYBOX_DEFAULT_ED
+	bool
+	default n
+config BUSYBOX_DEFAULT_PATCH
+	bool
+	default n
+config BUSYBOX_DEFAULT_SED
+	bool
+	default y
+config BUSYBOX_DEFAULT_VI
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_VI_MAX_LEN
+	int
+	default 1024
+config BUSYBOX_DEFAULT_FEATURE_VI_8BIT
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_VI_COLON
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_VI_COLON_EXPAND
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_VI_YANKMARK
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_VI_SEARCH
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_VI_REGEX_SEARCH
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_VI_USE_SIGNALS
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_VI_DOT_CMD
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_VI_READONLY
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_VI_SETOPTS
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_VI_SET
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_VI_WIN_RESIZE
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_VI_ASK_TERMINAL
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_VI_UNDO
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_VI_UNDO_QUEUE
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_VI_UNDO_QUEUE_MAX
+	int
+	default 0
+config BUSYBOX_DEFAULT_FEATURE_VI_VERBOSE_STATUS
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_ALLOW_EXEC
+	bool
+	default y
+config BUSYBOX_DEFAULT_FIND
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_FIND_PRINT0
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_FIND_MTIME
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_FIND_ATIME
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_FIND_CTIME
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_FIND_MMIN
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_FIND_AMIN
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_FIND_CMIN
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_FIND_PERM
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_FIND_TYPE
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_FIND_EXECUTABLE
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_FIND_XDEV
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_FIND_MAXDEPTH
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_FIND_NEWER
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_FIND_INUM
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_FIND_SAMEFILE
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_FIND_EXEC
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_FIND_EXEC_PLUS
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_FIND_USER
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_FIND_GROUP
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_FIND_NOT
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_FIND_DEPTH
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_FIND_PAREN
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_FIND_SIZE
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_FIND_PRUNE
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_FIND_QUIT
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_FIND_DELETE
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_FIND_EMPTY
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_FIND_PATH
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_FIND_REGEX
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_FIND_CONTEXT
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_FIND_LINKS
+	bool
+	default n
+config BUSYBOX_DEFAULT_GREP
+	bool
+	default y
+config BUSYBOX_DEFAULT_EGREP
+	bool
+	default y
+config BUSYBOX_DEFAULT_FGREP
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_GREP_CONTEXT
+	bool
+	default y
+config BUSYBOX_DEFAULT_XARGS
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_XARGS_SUPPORT_CONFIRMATION
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_XARGS_SUPPORT_QUOTES
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_XARGS_SUPPORT_TERMOPT
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_XARGS_SUPPORT_ZERO_TERM
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_XARGS_SUPPORT_REPL_STR
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_XARGS_SUPPORT_PARALLEL
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_XARGS_SUPPORT_ARGS_FILE
+	bool
+	default n
+config BUSYBOX_DEFAULT_BOOTCHARTD
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_BOOTCHARTD_BLOATED_HEADER
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_BOOTCHARTD_CONFIG_FILE
+	bool
+	default n
+config BUSYBOX_DEFAULT_HALT
+	bool
+	default y
+config BUSYBOX_DEFAULT_POWEROFF
+	bool
+	default y
+config BUSYBOX_DEFAULT_REBOOT
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_WAIT_FOR_INIT
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_CALL_TELINIT
+	bool
+	default n
+config BUSYBOX_DEFAULT_TELINIT_PATH
+	string
+	default ""
+config BUSYBOX_DEFAULT_INIT
+	bool
+	default n
+config BUSYBOX_DEFAULT_LINUXRC
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_USE_INITTAB
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_KILL_REMOVED
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_KILL_DELAY
+	int
+	default 0
+config BUSYBOX_DEFAULT_FEATURE_INIT_SCTTY
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_INIT_SYSLOG
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_INIT_QUIET
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_INIT_COREDUMPS
+	bool
+	default n
+config BUSYBOX_DEFAULT_INIT_TERMINAL_TYPE
+	string
+	default ""
+config BUSYBOX_DEFAULT_FEATURE_INIT_MODIFY_CMDLINE
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_SHADOWPASSWDS
+	bool
+	default y
+config BUSYBOX_DEFAULT_USE_BB_PWD_GRP
+	bool
+	default n
+config BUSYBOX_DEFAULT_USE_BB_SHADOW
+	bool
+	default n
+config BUSYBOX_DEFAULT_USE_BB_CRYPT
+	bool
+	default n
+config BUSYBOX_DEFAULT_USE_BB_CRYPT_SHA
+	bool
+	default y
+config BUSYBOX_DEFAULT_ADD_SHELL
+	bool
+	default n
+config BUSYBOX_DEFAULT_REMOVE_SHELL
+	bool
+	default n
+config BUSYBOX_DEFAULT_ADDGROUP
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_ADDUSER_TO_GROUP
+	bool
+	default n
+config BUSYBOX_DEFAULT_ADDUSER
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_CHECK_NAMES
+	bool
+	default n
+config BUSYBOX_DEFAULT_LAST_ID
+	int
+	default 0
+config BUSYBOX_DEFAULT_FIRST_SYSTEM_ID
+	int
+	default 0
+config BUSYBOX_DEFAULT_LAST_SYSTEM_ID
+	int
+	default 0
+config BUSYBOX_DEFAULT_CHPASSWD
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_DEFAULT_PASSWD_ALGO
+	string
+	default "sha256"
+config BUSYBOX_DEFAULT_CRYPTPW
+	bool
+	default n
+config BUSYBOX_DEFAULT_MKPASSWD
+	bool
+	default n
+config BUSYBOX_DEFAULT_DELUSER
+	bool
+	default n
+config BUSYBOX_DEFAULT_DELGROUP
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_DEL_USER_FROM_GROUP
+	bool
+	default n
+config BUSYBOX_DEFAULT_GETTY
+	bool
+	default n
+config BUSYBOX_DEFAULT_LOGIN
+	bool
+	default y
+config BUSYBOX_DEFAULT_LOGIN_SESSION_AS_CHILD
+	bool
+	default y
+config BUSYBOX_DEFAULT_LOGIN_SCRIPTS
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_NOLOGIN
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_SECURETTY
+	bool
+	default n
+config BUSYBOX_DEFAULT_PASSWD
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_PASSWD_WEAK_CHECK
+	bool
+	default y
+config BUSYBOX_DEFAULT_SU
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_SU_SYSLOG
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_SU_CHECKS_SHELLS
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_SU_BLANK_PW_NEEDS_SECURE_TTY
+	bool
+	default n
+config BUSYBOX_DEFAULT_SULOGIN
+	bool
+	default n
+config BUSYBOX_DEFAULT_VLOCK
+	bool
+	default n
+config BUSYBOX_DEFAULT_CHATTR
+	bool
+	default n
+config BUSYBOX_DEFAULT_FSCK
+	bool
+	default n
+config BUSYBOX_DEFAULT_LSATTR
+	bool
+	default n
+config BUSYBOX_DEFAULT_TUNE2FS
+	bool
+	default n
+config BUSYBOX_DEFAULT_MODPROBE_SMALL
+	bool
+	default n
+config BUSYBOX_DEFAULT_DEPMOD
+	bool
+	default n
+config BUSYBOX_DEFAULT_INSMOD
+	bool
+	default n
+config BUSYBOX_DEFAULT_LSMOD
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_LSMOD_PRETTY_2_6_OUTPUT
+	bool
+	default n
+config BUSYBOX_DEFAULT_MODINFO
+	bool
+	default n
+config BUSYBOX_DEFAULT_MODPROBE
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_MODPROBE_BLACKLIST
+	bool
+	default n
+config BUSYBOX_DEFAULT_RMMOD
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_CMDLINE_MODULE_OPTIONS
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_2_4_MODULES
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_INSMOD_VERSION_CHECKING
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_INSMOD_LOADINKMEM
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_INSMOD_LOAD_MAP
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_INSMOD_LOAD_MAP_FULL
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_CHECK_TAINTED_MODULE
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_INSMOD_TRY_MMAP
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_MODUTILS_ALIAS
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_MODUTILS_SYMBOLS
+	bool
+	default n
+config BUSYBOX_DEFAULT_DEFAULT_MODULES_DIR
+	string
+	default ""
+config BUSYBOX_DEFAULT_DEFAULT_DEPMOD_FILE
+	string
+	default ""
+config BUSYBOX_DEFAULT_ACPID
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_ACPID_COMPAT
+	bool
+	default n
+config BUSYBOX_DEFAULT_BLKDISCARD
+	bool
+	default n
+config BUSYBOX_DEFAULT_BLKID
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_BLKID_TYPE
+	bool
+	default n
+config BUSYBOX_DEFAULT_BLOCKDEV
+	bool
+	default n
+config BUSYBOX_DEFAULT_CAL
+	bool
+	default n
+config BUSYBOX_DEFAULT_CHRT
+	bool
+	default n
+config BUSYBOX_DEFAULT_DMESG
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_DMESG_PRETTY
+	bool
+	default y
+config BUSYBOX_DEFAULT_EJECT
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_EJECT_SCSI
+	bool
+	default n
+config BUSYBOX_DEFAULT_FALLOCATE
+	bool
+	default n
+config BUSYBOX_DEFAULT_FATATTR
+	bool
+	default n
+config BUSYBOX_DEFAULT_FBSET
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_FBSET_FANCY
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_FBSET_READMODE
+	bool
+	default n
+config BUSYBOX_DEFAULT_FDFORMAT
+	bool
+	default n
+config BUSYBOX_DEFAULT_FDISK
+	bool
+	default n
+config BUSYBOX_DEFAULT_FDISK_SUPPORT_LARGE_DISKS
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_FDISK_WRITABLE
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_AIX_LABEL
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_SGI_LABEL
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_SUN_LABEL
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_OSF_LABEL
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_GPT_LABEL
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_FDISK_ADVANCED
+	bool
+	default n
+config BUSYBOX_DEFAULT_FINDFS
+	bool
+	default n
+config BUSYBOX_DEFAULT_FLOCK
+	bool
+	default y
+config BUSYBOX_DEFAULT_FDFLUSH
+	bool
+	default n
+config BUSYBOX_DEFAULT_FREERAMDISK
+	bool
+	default n
+config BUSYBOX_DEFAULT_FSCK_MINIX
+	bool
+	default n
+config BUSYBOX_DEFAULT_FSFREEZE
+	bool
+	default n
+config BUSYBOX_DEFAULT_FSTRIM
+	bool
+	default n
+config BUSYBOX_DEFAULT_GETOPT
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_GETOPT_LONG
+	bool
+	default n
+config BUSYBOX_DEFAULT_HEXDUMP
+	bool
+	default y
+config BUSYBOX_DEFAULT_HD
+	bool
+	default n
+config BUSYBOX_DEFAULT_XXD
+	bool
+	default n
+config BUSYBOX_DEFAULT_HWCLOCK
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_HWCLOCK_ADJTIME_FHS
+	bool
+	default n
+config BUSYBOX_DEFAULT_IONICE
+	bool
+	default n
+config BUSYBOX_DEFAULT_IPCRM
+	bool
+	default n
+config BUSYBOX_DEFAULT_IPCS
+	bool
+	default n
+config BUSYBOX_DEFAULT_LAST
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_LAST_FANCY
+	bool
+	default n
+config BUSYBOX_DEFAULT_LOSETUP
+	bool
+	default n
+config BUSYBOX_DEFAULT_LSPCI
+	bool
+	default n
+config BUSYBOX_DEFAULT_LSUSB
+	bool
+	default n
+config BUSYBOX_DEFAULT_MDEV
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_MDEV_CONF
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_MDEV_RENAME
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_MDEV_RENAME_REGEXP
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_MDEV_EXEC
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_MDEV_LOAD_FIRMWARE
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_MDEV_DAEMON
+	bool
+	default n
+config BUSYBOX_DEFAULT_MESG
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_MESG_ENABLE_ONLY_GROUP
+	bool
+	default n
+config BUSYBOX_DEFAULT_MKE2FS
+	bool
+	default n
+config BUSYBOX_DEFAULT_MKFS_EXT2
+	bool
+	default n
+config BUSYBOX_DEFAULT_MKFS_MINIX
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_MINIX2
+	bool
+	default n
+config BUSYBOX_DEFAULT_MKFS_REISER
+	bool
+	default n
+config BUSYBOX_DEFAULT_MKDOSFS
+	bool
+	default n
+config BUSYBOX_DEFAULT_MKFS_VFAT
+	bool
+	default n
+config BUSYBOX_DEFAULT_MKSWAP
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_MKSWAP_UUID
+	bool
+	default n
+config BUSYBOX_DEFAULT_MORE
+	bool
+	default n
+config BUSYBOX_DEFAULT_MOUNT
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_MOUNT_FAKE
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_MOUNT_VERBOSE
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_MOUNT_HELPERS
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_MOUNT_LABEL
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_MOUNT_NFS
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_MOUNT_CIFS
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_MOUNT_FLAGS
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_MOUNT_FSTAB
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_MOUNT_OTHERTAB
+	bool
+	default n
+config BUSYBOX_DEFAULT_MOUNTPOINT
+	bool
+	default n
+config BUSYBOX_DEFAULT_NOLOGIN
+	bool
+	default n
+config BUSYBOX_DEFAULT_NOLOGIN_DEPENDENCIES
+	bool
+	default n
+config BUSYBOX_DEFAULT_NSENTER
+	bool
+	default n
+config BUSYBOX_DEFAULT_PIVOT_ROOT
+	bool
+	default y
+config BUSYBOX_DEFAULT_RDATE
+	bool
+	default n
+config BUSYBOX_DEFAULT_RDEV
+	bool
+	default n
+config BUSYBOX_DEFAULT_READPROFILE
+	bool
+	default n
+config BUSYBOX_DEFAULT_RENICE
+	bool
+	default n
+config BUSYBOX_DEFAULT_REV
+	bool
+	default n
+config BUSYBOX_DEFAULT_RTCWAKE
+	bool
+	default n
+config BUSYBOX_DEFAULT_SCRIPT
+	bool
+	default n
+config BUSYBOX_DEFAULT_SCRIPTREPLAY
+	bool
+	default n
+config BUSYBOX_DEFAULT_SETARCH
+	bool
+	default n
+config BUSYBOX_DEFAULT_LINUX32
+	bool
+	default n
+config BUSYBOX_DEFAULT_LINUX64
+	bool
+	default n
+config BUSYBOX_DEFAULT_SETPRIV
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_SETPRIV_DUMP
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_SETPRIV_CAPABILITIES
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_SETPRIV_CAPABILITY_NAMES
+	bool
+	default n
+config BUSYBOX_DEFAULT_SETSID
+	bool
+	default y
+config BUSYBOX_DEFAULT_SWAPON
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_SWAPON_DISCARD
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_SWAPON_PRI
+	bool
+	default y
+config BUSYBOX_DEFAULT_SWAPOFF
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_SWAPONOFF_LABEL
+	bool
+	default n
+config BUSYBOX_DEFAULT_SWITCH_ROOT
+	bool
+	default y
+config BUSYBOX_DEFAULT_TASKSET
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_TASKSET_FANCY
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_TASKSET_CPULIST
+	bool
+	default y
+config BUSYBOX_DEFAULT_UEVENT
+	bool
+	default n
+config BUSYBOX_DEFAULT_UMOUNT
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_UMOUNT_ALL
+	bool
+	default y
+config BUSYBOX_DEFAULT_UNSHARE
+	bool
+	default n
+config BUSYBOX_DEFAULT_WALL
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_MOUNT_LOOP
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_MOUNT_LOOP_CREATE
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_MTAB_SUPPORT
+	bool
+	default n
+config BUSYBOX_DEFAULT_VOLUMEID
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_VOLUMEID_BCACHE
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_VOLUMEID_BTRFS
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_VOLUMEID_CRAMFS
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_VOLUMEID_EROFS
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_VOLUMEID_EXFAT
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_VOLUMEID_EXT
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_VOLUMEID_F2FS
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_VOLUMEID_FAT
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_VOLUMEID_HFS
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_VOLUMEID_ISO9660
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_VOLUMEID_JFS
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_VOLUMEID_LFS
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_VOLUMEID_LINUXRAID
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_VOLUMEID_LINUXSWAP
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_VOLUMEID_LUKS
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_VOLUMEID_MINIX
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_VOLUMEID_NILFS
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_VOLUMEID_NTFS
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_VOLUMEID_OCFS2
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_VOLUMEID_REISERFS
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_VOLUMEID_ROMFS
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_VOLUMEID_SQUASHFS
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_VOLUMEID_SYSV
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_VOLUMEID_UBIFS
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_VOLUMEID_UDF
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_VOLUMEID_XFS
+	bool
+	default n
+config BUSYBOX_DEFAULT_ADJTIMEX
+	bool
+	default n
+config BUSYBOX_DEFAULT_ASCII
+	bool
+	default n
+config BUSYBOX_DEFAULT_BBCONFIG
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_COMPRESS_BBCONFIG
+	bool
+	default n
+config BUSYBOX_DEFAULT_BC
+	bool
+	default n
+config BUSYBOX_DEFAULT_DC
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_DC_BIG
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_DC_LIBM
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_BC_INTERACTIVE
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_BC_LONG_OPTIONS
+	bool
+	default n
+config BUSYBOX_DEFAULT_BEEP
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_BEEP_FREQ
+	int
+	default 0
+config BUSYBOX_DEFAULT_FEATURE_BEEP_LENGTH_MS
+	int
+	default 0
+config BUSYBOX_DEFAULT_CHAT
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_CHAT_NOFAIL
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_CHAT_TTY_HIFI
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_CHAT_IMPLICIT_CR
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_CHAT_SWALLOW_OPTS
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_CHAT_SEND_ESCAPES
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_CHAT_VAR_ABORT_LEN
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_CHAT_CLR_ABORT
+	bool
+	default n
+config BUSYBOX_DEFAULT_CONSPY
+	bool
+	default n
+config BUSYBOX_DEFAULT_CROND
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_CROND_D
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_CROND_CALL_SENDMAIL
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_CROND_SPECIAL_TIMES
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_CROND_DIR
+	string
+	default "/etc"
+config BUSYBOX_DEFAULT_CRONTAB
+	bool
+	default y
+config BUSYBOX_DEFAULT_DEVFSD
+	bool
+	default n
+config BUSYBOX_DEFAULT_DEVFSD_MODLOAD
+	bool
+	default n
+config BUSYBOX_DEFAULT_DEVFSD_FG_NP
+	bool
+	default n
+config BUSYBOX_DEFAULT_DEVFSD_VERBOSE
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_DEVFS
+	bool
+	default n
+config BUSYBOX_DEFAULT_DEVMEM
+	bool
+	default n
+config BUSYBOX_DEFAULT_FBSPLASH
+	bool
+	default n
+config BUSYBOX_DEFAULT_FLASH_ERASEALL
+	bool
+	default n
+config BUSYBOX_DEFAULT_FLASH_LOCK
+	bool
+	default n
+config BUSYBOX_DEFAULT_FLASH_UNLOCK
+	bool
+	default n
+config BUSYBOX_DEFAULT_FLASHCP
+	bool
+	default n
+config BUSYBOX_DEFAULT_HDPARM
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_HDPARM_GET_IDENTITY
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_HDPARM_HDIO_SCAN_HWIF
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_HDPARM_HDIO_DRIVE_RESET
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_HDPARM_HDIO_TRISTATE_HWIF
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_HDPARM_HDIO_GETSET_DMA
+	bool
+	default n
+config BUSYBOX_DEFAULT_HEXEDIT
+	bool
+	default n
+config BUSYBOX_DEFAULT_I2CGET
+	bool
+	default n
+config BUSYBOX_DEFAULT_I2CSET
+	bool
+	default n
+config BUSYBOX_DEFAULT_I2CDUMP
+	bool
+	default n
+config BUSYBOX_DEFAULT_I2CDETECT
+	bool
+	default n
+config BUSYBOX_DEFAULT_I2CTRANSFER
+	bool
+	default n
+config BUSYBOX_DEFAULT_INOTIFYD
+	bool
+	default n
+config BUSYBOX_DEFAULT_LESS
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_LESS_MAXLINES
+	int
+	default 9999999
+config BUSYBOX_DEFAULT_FEATURE_LESS_BRACKETS
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_LESS_FLAGS
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_LESS_TRUNCATE
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_LESS_MARKS
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_LESS_REGEXP
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_LESS_WINCH
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_LESS_ASK_TERMINAL
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_LESS_DASHCMD
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_LESS_LINENUMS
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_LESS_RAW
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_LESS_ENV
+	bool
+	default n
+config BUSYBOX_DEFAULT_LOCK
+	bool
+	default y
+config BUSYBOX_DEFAULT_LSSCSI
+	bool
+	default n
+config BUSYBOX_DEFAULT_MAKEDEVS
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_MAKEDEVS_LEAF
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_MAKEDEVS_TABLE
+	bool
+	default n
+config BUSYBOX_DEFAULT_MAN
+	bool
+	default n
+config BUSYBOX_DEFAULT_MICROCOM
+	bool
+	default n
+config BUSYBOX_DEFAULT_MIM
+	bool
+	default n
+config BUSYBOX_DEFAULT_MT
+	bool
+	default n
+config BUSYBOX_DEFAULT_NANDWRITE
+	bool
+	default n
+config BUSYBOX_DEFAULT_NANDDUMP
+	bool
+	default n
+config BUSYBOX_DEFAULT_PARTPROBE
+	bool
+	default n
+config BUSYBOX_DEFAULT_RAIDAUTORUN
+	bool
+	default n
+config BUSYBOX_DEFAULT_READAHEAD
+	bool
+	default n
+config BUSYBOX_DEFAULT_RFKILL
+	bool
+	default n
+config BUSYBOX_DEFAULT_RUNLEVEL
+	bool
+	default n
+config BUSYBOX_DEFAULT_RX
+	bool
+	default n
+config BUSYBOX_DEFAULT_SEEDRNG
+	bool
+	default n
+config BUSYBOX_DEFAULT_SETFATTR
+	bool
+	default n
+config BUSYBOX_DEFAULT_SETSERIAL
+	bool
+	default n
+config BUSYBOX_DEFAULT_STRINGS
+	bool
+	default y
+config BUSYBOX_DEFAULT_TIME
+	bool
+	default y
+config BUSYBOX_DEFAULT_TREE
+	bool
+	default n
+config BUSYBOX_DEFAULT_TS
+	bool
+	default n
+config BUSYBOX_DEFAULT_TTYSIZE
+	bool
+	default n
+config BUSYBOX_DEFAULT_UBIATTACH
+	bool
+	default n
+config BUSYBOX_DEFAULT_UBIDETACH
+	bool
+	default n
+config BUSYBOX_DEFAULT_UBIMKVOL
+	bool
+	default n
+config BUSYBOX_DEFAULT_UBIRMVOL
+	bool
+	default n
+config BUSYBOX_DEFAULT_UBIRSVOL
+	bool
+	default n
+config BUSYBOX_DEFAULT_UBIUPDATEVOL
+	bool
+	default n
+config BUSYBOX_DEFAULT_UBIRENAME
+	bool
+	default n
+config BUSYBOX_DEFAULT_VOLNAME
+	bool
+	default n
+config BUSYBOX_DEFAULT_WATCHDOG
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_WATCHDOG_OPEN_TWICE
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_IPV6
+	bool
+	default y if IPV6
+	default n
+config BUSYBOX_DEFAULT_FEATURE_UNIX_LOCAL
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_PREFER_IPV4_ADDRESS
+	bool
+	default n
+config BUSYBOX_DEFAULT_VERBOSE_RESOLUTION_ERRORS
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_ETC_NETWORKS
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_ETC_SERVICES
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_HWIB
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_TLS_SHA1
+	bool
+	default n
+config BUSYBOX_DEFAULT_ARP
+	bool
+	default n
+config BUSYBOX_DEFAULT_ARPING
+	bool
+	default n
+config BUSYBOX_DEFAULT_BRCTL
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_BRCTL_FANCY
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_BRCTL_SHOW
+	bool
+	default y
+config BUSYBOX_DEFAULT_DNSD
+	bool
+	default n
+config BUSYBOX_DEFAULT_ETHER_WAKE
+	bool
+	default n
+config BUSYBOX_DEFAULT_FTPD
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_FTPD_WRITE
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_FTPD_ACCEPT_BROKEN_LIST
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_FTPD_AUTHENTICATION
+	bool
+	default n
+config BUSYBOX_DEFAULT_FTPGET
+	bool
+	default n
+config BUSYBOX_DEFAULT_FTPPUT
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_FTPGETPUT_LONG_OPTIONS
+	bool
+	default n
+config BUSYBOX_DEFAULT_HOSTNAME
+	bool
+	default n
+config BUSYBOX_DEFAULT_DNSDOMAINNAME
+	bool
+	default n
+config BUSYBOX_DEFAULT_HTTPD
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_HTTPD_PORT_DEFAULT
+	int
+	default 80
+config BUSYBOX_DEFAULT_FEATURE_HTTPD_RANGES
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_HTTPD_SETUID
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_HTTPD_BASIC_AUTH
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_HTTPD_AUTH_MD5
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_HTTPD_CGI
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_HTTPD_ENCODE_URL_STR
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_HTTPD_ERROR_PAGES
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_HTTPD_PROXY
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_HTTPD_GZIP
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_HTTPD_ETAG
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_HTTPD_LAST_MODIFIED
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_HTTPD_DATE
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_HTTPD_ACL_IP
+	bool
+	default n
+config BUSYBOX_DEFAULT_IFCONFIG
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_IFCONFIG_STATUS
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_IFCONFIG_SLIP
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_IFCONFIG_HW
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_IFCONFIG_BROADCAST_PLUS
+	bool
+	default y
+config BUSYBOX_DEFAULT_IFENSLAVE
+	bool
+	default n
+config BUSYBOX_DEFAULT_IFPLUGD
+	bool
+	default n
+config BUSYBOX_DEFAULT_IFUP
+	bool
+	default n
+config BUSYBOX_DEFAULT_IFDOWN
+	bool
+	default n
+config BUSYBOX_DEFAULT_IFUPDOWN_IFSTATE_PATH
+	string
+	default ""
+config BUSYBOX_DEFAULT_FEATURE_IFUPDOWN_IP
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_IFUPDOWN_IPV4
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_IFUPDOWN_IPV6
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_IFUPDOWN_MAPPING
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_IFUPDOWN_EXTERNAL_DHCP
+	bool
+	default n
+config BUSYBOX_DEFAULT_INETD
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_INETD_SUPPORT_BUILTIN_ECHO
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_INETD_SUPPORT_BUILTIN_TIME
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_INETD_RPC
+	bool
+	default n
+config BUSYBOX_DEFAULT_IP
+	bool
+	default y
+config BUSYBOX_DEFAULT_IPADDR
+	bool
+	default n
+config BUSYBOX_DEFAULT_IPLINK
+	bool
+	default n
+config BUSYBOX_DEFAULT_IPROUTE
+	bool
+	default y
+config BUSYBOX_DEFAULT_IPTUNNEL
+	bool
+	default n
+config BUSYBOX_DEFAULT_IPRULE
+	bool
+	default n
+config BUSYBOX_DEFAULT_IPNEIGH
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_IP_ADDRESS
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_IP_LINK
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_IP_ROUTE
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_IP_ROUTE_DIR
+	string
+	default "/etc/iproute2"
+config BUSYBOX_DEFAULT_FEATURE_IP_TUNNEL
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_IP_RULE
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_IP_NEIGH
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_IP_RARE_PROTOCOLS
+	bool
+	default n
+config BUSYBOX_DEFAULT_IPCALC
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_IPCALC_LONG_OPTIONS
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_IPCALC_FANCY
+	bool
+	default n
+config BUSYBOX_DEFAULT_FAKEIDENTD
+	bool
+	default n
+config BUSYBOX_DEFAULT_NAMEIF
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_NAMEIF_EXTENDED
+	bool
+	default n
+config BUSYBOX_DEFAULT_NBDCLIENT
+	bool
+	default n
+config BUSYBOX_DEFAULT_NC
+	bool
+	default y
+config BUSYBOX_DEFAULT_NETCAT
+	bool
+	default n
+config BUSYBOX_DEFAULT_NC_SERVER
+	bool
+	default n
+config BUSYBOX_DEFAULT_NC_EXTRA
+	bool
+	default n
+config BUSYBOX_DEFAULT_NC_110_COMPAT
+	bool
+	default n
+config BUSYBOX_DEFAULT_NETMSG
+	bool
+	default y
+config BUSYBOX_DEFAULT_NETSTAT
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_NETSTAT_WIDE
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_NETSTAT_PRG
+	bool
+	default y
+config BUSYBOX_DEFAULT_NSLOOKUP
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_NSLOOKUP_BIG
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_NSLOOKUP_LONG_OPTIONS
+	bool
+	default n
+config BUSYBOX_DEFAULT_NTPD
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_NTPD_SERVER
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_NTPD_CONF
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_NTP_AUTH
+	bool
+	default n
+config BUSYBOX_DEFAULT_PING
+	bool
+	default y
+config BUSYBOX_DEFAULT_PING6
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_FANCY_PING
+	bool
+	default y
+config BUSYBOX_DEFAULT_PSCAN
+	bool
+	default n
+config BUSYBOX_DEFAULT_ROUTE
+	bool
+	default y
+config BUSYBOX_DEFAULT_SLATTACH
+	bool
+	default n
+config BUSYBOX_DEFAULT_SSL_CLIENT
+	bool
+	default n
+config BUSYBOX_DEFAULT_TC
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_TC_INGRESS
+	bool
+	default n
+config BUSYBOX_DEFAULT_TCPSVD
+	bool
+	default n
+config BUSYBOX_DEFAULT_UDPSVD
+	bool
+	default n
+config BUSYBOX_DEFAULT_TELNET
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_TELNET_TTYPE
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_TELNET_AUTOLOGIN
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_TELNET_WIDTH
+	bool
+	default n
+config BUSYBOX_DEFAULT_TELNETD
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_TELNETD_STANDALONE
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_TELNETD_PORT_DEFAULT
+	int
+	default 23
+config BUSYBOX_DEFAULT_FEATURE_TELNETD_INETD_WAIT
+	bool
+	default n
+config BUSYBOX_DEFAULT_TFTP
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_TFTP_PROGRESS_BAR
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_TFTP_HPA_COMPAT
+	bool
+	default n
+config BUSYBOX_DEFAULT_TFTPD
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_TFTP_GET
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_TFTP_PUT
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_TFTP_BLOCKSIZE
+	bool
+	default n
+config BUSYBOX_DEFAULT_TFTP_DEBUG
+	bool
+	default n
+config BUSYBOX_DEFAULT_TLS
+	bool
+	default n
+config BUSYBOX_DEFAULT_TRACEROUTE
+	bool
+	default y
+config BUSYBOX_DEFAULT_TRACEROUTE6
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_TRACEROUTE_VERBOSE
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_TRACEROUTE_USE_ICMP
+	bool
+	default n
+config BUSYBOX_DEFAULT_TUNCTL
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_TUNCTL_UG
+	bool
+	default n
+config BUSYBOX_DEFAULT_VCONFIG
+	bool
+	default n
+config BUSYBOX_DEFAULT_WGET
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_WGET_LONG_OPTIONS
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_WGET_STATUSBAR
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_WGET_FTP
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_WGET_AUTHENTICATION
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_WGET_TIMEOUT
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_WGET_HTTPS
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_WGET_OPENSSL
+	bool
+	default n
+config BUSYBOX_DEFAULT_WHOIS
+	bool
+	default n
+config BUSYBOX_DEFAULT_ZCIP
+	bool
+	default n
+config BUSYBOX_DEFAULT_UDHCPD
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_UDHCPD_BASE_IP_ON_MAC
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_UDHCPD_WRITE_LEASES_EARLY
+	bool
+	default n
+config BUSYBOX_DEFAULT_DHCPD_LEASES_FILE
+	string
+	default ""
+config BUSYBOX_DEFAULT_DUMPLEASES
+	bool
+	default n
+config BUSYBOX_DEFAULT_DHCPRELAY
+	bool
+	default n
+config BUSYBOX_DEFAULT_UDHCPC
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_UDHCPC_ARPING
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_UDHCPC_SANITIZEOPT
+	bool
+	default n
+config BUSYBOX_DEFAULT_UDHCPC_DEFAULT_SCRIPT
+	string
+	default "/usr/share/udhcpc/default.script"
+config BUSYBOX_DEFAULT_UDHCPC6_DEFAULT_SCRIPT
+	string
+	default ""
+config BUSYBOX_DEFAULT_UDHCPC6
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_UDHCPC6_RFC3646
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_UDHCPC6_RFC4704
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_UDHCPC6_RFC4833
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_UDHCPC6_RFC5970
+	bool
+	default n
+config BUSYBOX_DEFAULT_UDHCPC_DEFAULT_INTERFACE
+	string
+	default ""
+config BUSYBOX_DEFAULT_FEATURE_UDHCP_PORT
+	bool
+	default n
+config BUSYBOX_DEFAULT_UDHCP_DEBUG
+	int
+	default 0
+config BUSYBOX_DEFAULT_UDHCPC_SLACK_FOR_BUGGY_SERVERS
+	int
+	default 80
+config BUSYBOX_DEFAULT_FEATURE_UDHCP_RFC3397
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_UDHCP_8021Q
+	bool
+	default n
+config BUSYBOX_DEFAULT_IFUPDOWN_UDHCPC_CMD_OPTIONS
+	string
+	default ""
+config BUSYBOX_DEFAULT_LPD
+	bool
+	default n
+config BUSYBOX_DEFAULT_LPR
+	bool
+	default n
+config BUSYBOX_DEFAULT_LPQ
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_MIME_CHARSET
+	string
+	default ""
+config BUSYBOX_DEFAULT_MAKEMIME
+	bool
+	default n
+config BUSYBOX_DEFAULT_POPMAILDIR
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_POPMAILDIR_DELIVERY
+	bool
+	default n
+config BUSYBOX_DEFAULT_REFORMIME
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_REFORMIME_COMPAT
+	bool
+	default n
+config BUSYBOX_DEFAULT_SENDMAIL
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_FAST_TOP
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_SHOW_THREADS
+	bool
+	default n
+config BUSYBOX_DEFAULT_FREE
+	bool
+	default y
+config BUSYBOX_DEFAULT_FUSER
+	bool
+	default n
+config BUSYBOX_DEFAULT_IOSTAT
+	bool
+	default n
+config BUSYBOX_DEFAULT_KILL
+	bool
+	default y
+config BUSYBOX_DEFAULT_KILLALL
+	bool
+	default y
+config BUSYBOX_DEFAULT_KILLALL5
+	bool
+	default n
+config BUSYBOX_DEFAULT_LSOF
+	bool
+	default n
+config BUSYBOX_DEFAULT_MPSTAT
+	bool
+	default n
+config BUSYBOX_DEFAULT_NMETER
+	bool
+	default n
+config BUSYBOX_DEFAULT_PGREP
+	bool
+	default y
+config BUSYBOX_DEFAULT_PKILL
+	bool
+	default n
+config BUSYBOX_DEFAULT_PIDOF
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_PIDOF_SINGLE
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_PIDOF_OMIT
+	bool
+	default n
+config BUSYBOX_DEFAULT_PMAP
+	bool
+	default n
+config BUSYBOX_DEFAULT_POWERTOP
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_POWERTOP_INTERACTIVE
+	bool
+	default n
+config BUSYBOX_DEFAULT_PS
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_PS_WIDE
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_PS_LONG
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_PS_TIME
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_PS_UNUSUAL_SYSTEMS
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_PS_ADDITIONAL_COLUMNS
+	bool
+	default n
+config BUSYBOX_DEFAULT_PSTREE
+	bool
+	default n
+config BUSYBOX_DEFAULT_PWDX
+	bool
+	default n
+config BUSYBOX_DEFAULT_SMEMCAP
+	bool
+	default n
+config BUSYBOX_DEFAULT_BB_SYSCTL
+	bool
+	default y
+config BUSYBOX_DEFAULT_TOP
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_TOP_INTERACTIVE
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_TOP_CPU_USAGE_PERCENTAGE
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_TOP_CPU_GLOBAL_PERCENTS
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_TOP_SMP_CPU
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_TOP_DECIMALS
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_TOP_SMP_PROCESS
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_TOPMEM
+	bool
+	default n
+config BUSYBOX_DEFAULT_UPTIME
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_UPTIME_UTMP_SUPPORT
+	bool
+	default n
+config BUSYBOX_DEFAULT_WATCH
+	bool
+	default n
+config BUSYBOX_DEFAULT_CHPST
+	bool
+	default n
+config BUSYBOX_DEFAULT_SETUIDGID
+	bool
+	default n
+config BUSYBOX_DEFAULT_ENVUIDGID
+	bool
+	default n
+config BUSYBOX_DEFAULT_ENVDIR
+	bool
+	default n
+config BUSYBOX_DEFAULT_SOFTLIMIT
+	bool
+	default n
+config BUSYBOX_DEFAULT_RUNSV
+	bool
+	default n
+config BUSYBOX_DEFAULT_RUNSVDIR
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_RUNSVDIR_LOG
+	bool
+	default n
+config BUSYBOX_DEFAULT_SV
+	bool
+	default n
+config BUSYBOX_DEFAULT_SV_DEFAULT_SERVICE_DIR
+	string
+	default ""
+config BUSYBOX_DEFAULT_SVC
+	bool
+	default n
+config BUSYBOX_DEFAULT_SVOK
+	bool
+	default n
+config BUSYBOX_DEFAULT_SVLOGD
+	bool
+	default n
+config BUSYBOX_DEFAULT_CHCON
+	bool
+	default n
+config BUSYBOX_DEFAULT_GETENFORCE
+	bool
+	default n
+config BUSYBOX_DEFAULT_GETSEBOOL
+	bool
+	default n
+config BUSYBOX_DEFAULT_LOAD_POLICY
+	bool
+	default n
+config BUSYBOX_DEFAULT_MATCHPATHCON
+	bool
+	default n
+config BUSYBOX_DEFAULT_RUNCON
+	bool
+	default n
+config BUSYBOX_DEFAULT_SELINUXENABLED
+	bool
+	default n
+config BUSYBOX_DEFAULT_SESTATUS
+	bool
+	default n
+config BUSYBOX_DEFAULT_SETENFORCE
+	bool
+	default n
+config BUSYBOX_DEFAULT_SETFILES
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_SETFILES_CHECK_OPTION
+	bool
+	default n
+config BUSYBOX_DEFAULT_RESTORECON
+	bool
+	default n
+config BUSYBOX_DEFAULT_SETSEBOOL
+	bool
+	default n
+config BUSYBOX_DEFAULT_SH_IS_ASH
+	bool
+	default y
+config BUSYBOX_DEFAULT_SH_IS_HUSH
+	bool
+	default n
+config BUSYBOX_DEFAULT_SH_IS_NONE
+	bool
+	default n
+config BUSYBOX_DEFAULT_BASH_IS_ASH
+	bool
+	default n
+config BUSYBOX_DEFAULT_BASH_IS_HUSH
+	bool
+	default n
+config BUSYBOX_DEFAULT_BASH_IS_NONE
+	bool
+	default y
+config BUSYBOX_DEFAULT_SHELL_ASH
+	bool
+	default y
+config BUSYBOX_DEFAULT_ASH
+	bool
+	default y
+config BUSYBOX_DEFAULT_ASH_OPTIMIZE_FOR_SIZE
+	bool
+	default n
+config BUSYBOX_DEFAULT_ASH_INTERNAL_GLOB
+	bool
+	default y
+config BUSYBOX_DEFAULT_ASH_BASH_COMPAT
+	bool
+	default y
+config BUSYBOX_DEFAULT_ASH_BASH_SOURCE_CURDIR
+	bool
+	default n
+config BUSYBOX_DEFAULT_ASH_BASH_NOT_FOUND_HOOK
+	bool
+	default n
+config BUSYBOX_DEFAULT_ASH_JOB_CONTROL
+	bool
+	default y
+config BUSYBOX_DEFAULT_ASH_ALIAS
+	bool
+	default y
+config BUSYBOX_DEFAULT_ASH_RANDOM_SUPPORT
+	bool
+	default y
+config BUSYBOX_DEFAULT_ASH_EXPAND_PRMT
+	bool
+	default y
+config BUSYBOX_DEFAULT_ASH_IDLE_TIMEOUT
+	bool
+	default n
+config BUSYBOX_DEFAULT_ASH_MAIL
+	bool
+	default n
+config BUSYBOX_DEFAULT_ASH_ECHO
+	bool
+	default y
+config BUSYBOX_DEFAULT_ASH_PRINTF
+	bool
+	default y
+config BUSYBOX_DEFAULT_ASH_TEST
+	bool
+	default y
+config BUSYBOX_DEFAULT_ASH_SLEEP
+	bool
+	default n
+config BUSYBOX_DEFAULT_ASH_HELP
+	bool
+	default n
+config BUSYBOX_DEFAULT_ASH_GETOPTS
+	bool
+	default y
+config BUSYBOX_DEFAULT_ASH_CMDCMD
+	bool
+	default y
+config BUSYBOX_DEFAULT_CTTYHACK
+	bool
+	default n
+config BUSYBOX_DEFAULT_HUSH
+	bool
+	default n
+config BUSYBOX_DEFAULT_SHELL_HUSH
+	bool
+	default n
+config BUSYBOX_DEFAULT_HUSH_BASH_COMPAT
+	bool
+	default n
+config BUSYBOX_DEFAULT_HUSH_BRACE_EXPANSION
+	bool
+	default n
+config BUSYBOX_DEFAULT_HUSH_BASH_SOURCE_CURDIR
+	bool
+	default n
+config BUSYBOX_DEFAULT_HUSH_LINENO_VAR
+	bool
+	default n
+config BUSYBOX_DEFAULT_HUSH_INTERACTIVE
+	bool
+	default n
+config BUSYBOX_DEFAULT_HUSH_SAVEHISTORY
+	bool
+	default n
+config BUSYBOX_DEFAULT_HUSH_JOB
+	bool
+	default n
+config BUSYBOX_DEFAULT_HUSH_TICK
+	bool
+	default n
+config BUSYBOX_DEFAULT_HUSH_IF
+	bool
+	default n
+config BUSYBOX_DEFAULT_HUSH_LOOPS
+	bool
+	default n
+config BUSYBOX_DEFAULT_HUSH_CASE
+	bool
+	default n
+config BUSYBOX_DEFAULT_HUSH_FUNCTIONS
+	bool
+	default n
+config BUSYBOX_DEFAULT_HUSH_LOCAL
+	bool
+	default n
+config BUSYBOX_DEFAULT_HUSH_RANDOM_SUPPORT
+	bool
+	default n
+config BUSYBOX_DEFAULT_HUSH_MODE_X
+	bool
+	default n
+config BUSYBOX_DEFAULT_HUSH_ECHO
+	bool
+	default n
+config BUSYBOX_DEFAULT_HUSH_PRINTF
+	bool
+	default n
+config BUSYBOX_DEFAULT_HUSH_TEST
+	bool
+	default n
+config BUSYBOX_DEFAULT_HUSH_HELP
+	bool
+	default n
+config BUSYBOX_DEFAULT_HUSH_EXPORT
+	bool
+	default n
+config BUSYBOX_DEFAULT_HUSH_EXPORT_N
+	bool
+	default n
+config BUSYBOX_DEFAULT_HUSH_READONLY
+	bool
+	default n
+config BUSYBOX_DEFAULT_HUSH_KILL
+	bool
+	default n
+config BUSYBOX_DEFAULT_HUSH_WAIT
+	bool
+	default n
+config BUSYBOX_DEFAULT_HUSH_COMMAND
+	bool
+	default n
+config BUSYBOX_DEFAULT_HUSH_TRAP
+	bool
+	default n
+config BUSYBOX_DEFAULT_HUSH_TYPE
+	bool
+	default n
+config BUSYBOX_DEFAULT_HUSH_TIMES
+	bool
+	default n
+config BUSYBOX_DEFAULT_HUSH_READ
+	bool
+	default n
+config BUSYBOX_DEFAULT_HUSH_SET
+	bool
+	default n
+config BUSYBOX_DEFAULT_HUSH_UNSET
+	bool
+	default n
+config BUSYBOX_DEFAULT_HUSH_ULIMIT
+	bool
+	default n
+config BUSYBOX_DEFAULT_HUSH_UMASK
+	bool
+	default n
+config BUSYBOX_DEFAULT_HUSH_GETOPTS
+	bool
+	default n
+config BUSYBOX_DEFAULT_HUSH_MEMLEAK
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_SH_MATH
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_SH_MATH_64
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_SH_MATH_BASE
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_SH_EXTRA_QUIET
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_SH_STANDALONE
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_SH_NOFORK
+	bool
+	default y
+config BUSYBOX_DEFAULT_FEATURE_SH_READ_FRAC
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_SH_HISTFILESIZE
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_SH_EMBEDDED_SCRIPTS
+	bool
+	default n
+config BUSYBOX_DEFAULT_KLOGD
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_KLOGD_KLOGCTL
+	bool
+	default n
+config BUSYBOX_DEFAULT_LOGGER
+	bool
+	default y
+config BUSYBOX_DEFAULT_LOGREAD
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_LOGREAD_REDUCED_LOCKING
+	bool
+	default n
+config BUSYBOX_DEFAULT_SYSLOGD
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_ROTATE_LOGFILE
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_REMOTE_LOG
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_SYSLOGD_DUP
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_SYSLOGD_CFG
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_SYSLOGD_PRECISE_TIMESTAMPS
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_SYSLOGD_READ_BUFFER_SIZE
+	int
+	default 0
+config BUSYBOX_DEFAULT_FEATURE_IPC_SYSLOG
+	bool
+	default n
+config BUSYBOX_DEFAULT_FEATURE_IPC_SYSLOG_BUFFER_SIZE
+	int
+	default 0
+config BUSYBOX_DEFAULT_FEATURE_KMSG_SYSLOG
+	bool
+	default n
diff --git a/package/utils/busybox/Config.in b/package/utils/busybox/Config.in
new file mode 100644
index 0000000..dcd027e
--- /dev/null
+++ b/package/utils/busybox/Config.in
@@ -0,0 +1,21 @@
+if PACKAGE_busybox || PACKAGE_busybox-selinux
+
+config BUSYBOX_CUSTOM
+	bool "Customize busybox options"
+	default n
+        help
+          Enabling this allows full customization of busybox settings.
+          Note that there are many options here that can result in a build
+          that doesn't work properly.  Enabling customization will mark your
+          build as "tainted" for the purpose of bug reports.
+          See the variables written to /etc/openwrt_release
+
+          Unless you know what you are doing, you should leave this as 'n'
+
+	source "Config-defaults.in"
+
+	if BUSYBOX_CUSTOM
+	source "config/Config.in"
+	endif
+
+endif
diff --git a/package/utils/busybox/Makefile b/package/utils/busybox/Makefile
new file mode 100644
index 0000000..7d302bd
--- /dev/null
+++ b/package/utils/busybox/Makefile
@@ -0,0 +1,166 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# Copyright (C) 2006-2021 OpenWrt.org
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=busybox
+PKG_VERSION:=1.36.1
+PKG_RELEASE:=2
+PKG_FLAGS:=essential
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=https://www.busybox.net/downloads \
+		https://sources.buildroot.net/$(PKG_NAME)
+PKG_HASH:=b8cc24c9574d809e7279c3be349795c5d5ceb6fdf19ca709f80cde50e47de314
+
+PKG_BUILD_DEPENDS:=BUSYBOX_CONFIG_PAM:libpam
+PKG_BUILD_PARALLEL:=1
+PKG_BUILD_FLAGS:=lto
+ifeq ($(CONFIG_SOFT_FLOAT),)
+  PKG_BUILD_FLAGS+=no-mips16
+endif
+
+PKG_CHECK_FORMAT_SECURITY:=0
+
+PKG_LICENSE:=GPL-2.0
+PKG_LICENSE_FILES:=LICENSE archival/libarchive/bz/LICENSE
+PKG_CPE_ID:=cpe:/a:busybox:busybox
+
+BUSYBOX_SYM=$(if $(CONFIG_BUSYBOX_CUSTOM),CONFIG,DEFAULT)
+BUSYBOX_IF_ENABLED=$(if $(CONFIG_BUSYBOX_$(BUSYBOX_SYM)_$(1)),$(2))
+
+ifneq ($(CONFIG_BUSYBOX_$(BUSYBOX_SYM)_FEATURE_SUID),)
+  PKG_FILE_MODES:=/bin/busybox:root:root:4755
+endif
+
+include $(INCLUDE_DIR)/package.mk
+
+ifeq ($(DUMP),)
+  STAMP_CONFIGURED:=$(strip $(STAMP_CONFIGURED))_$(shell grep '^CONFIG_BUSYBOX_' $(TOPDIR)/.config | $(MKHASH) md5)
+endif
+
+# All files provided by busybox will serve as fallback alternatives by opkg.
+# There should be no need to enumerate ALTERNATIVES entries here
+define Package/busybox/Default
+  SECTION:=base
+  CATEGORY:=Base system
+  MAINTAINER:=Felix Fietkau <nbd@nbd.name>
+  TITLE:=Core utilities for embedded Linux
+  URL:=http://busybox.net/
+  DEPENDS:=+BUSYBOX_CONFIG_PAM:libpam +BUSYBOX_CONFIG_NTPD:jsonfilter
+  USERID:=ntp=123:ntp=123
+endef
+
+define Package/busybox
+  $(call Package/busybox/Default)
+  CONFLICTS:=busybox-selinux
+  VARIANT:=default
+endef
+
+define Package/busybox-selinux
+  $(call Package/busybox/Default)
+  TITLE += with SELinux support
+  DEPENDS += +libselinux
+  VARIANT:=selinux
+  PROVIDES:=busybox
+endef
+
+define Package/busybox/description
+ The Swiss Army Knife of embedded Linux.
+ It slices, it dices, it makes Julian Fries.
+endef
+
+define Package/busybox/config
+	source "$(SOURCE)/Config.in"
+endef
+
+ifneq ($(CONFIG_BUSYBOX_$(BUSYBOX_SYM)_FEATURE_SYSLOG)$(CONFIG_BUSYBOX_$(BUSYBOX_SYM)_FEATURE_SYSLOGD_CFG),)
+define Package/busybox/conffiles/syslog
+/etc/syslog.conf
+endef
+endif
+
+ifneq ($(CONFIG_BUSYBOX_$(BUSYBOX_SYM)_CROND),)
+define Package/busybox/conffiles/crond
+/etc/crontabs/
+endef
+endif
+
+define Package/busybox/conffiles
+$(Package/busybox/conffiles/syslog)
+$(Package/busybox/conffiles/crond)
+endef
+
+Package/busybox-selinux/conffiles = $(Package/busybox/conffiles)
+
+ifndef CONFIG_USE_MUSL
+LDLIBS:=m crypt
+endif
+
+LDLIBS += $(call BUSYBOX_IF_ENABLED,PAM,pam pam_misc pthread)
+
+ifeq ($(CONFIG_USE_GLIBC),y)
+  LDLIBS += $(call BUSYBOX_IF_ENABLED,NSLOOKUP,resolv)
+endif
+
+ifeq ($(BUILD_VARIANT),selinux)
+  LDLIBS += selinux sepol
+endif
+
+MAKE_VARS :=
+MAKE_FLAGS += \
+	EXTRA_CFLAGS="$(TARGET_CFLAGS) $(TARGET_CPPFLAGS)" \
+	EXTRA_LDFLAGS="$(TARGET_LDFLAGS) $(TARGET_CFLAGS)" \
+	LDLIBS="$(LDLIBS)" \
+	LD="$(TARGET_CC)" \
+	SKIP_STRIP=y
+ifneq ($(findstring c,$(OPENWRT_VERBOSE)),)
+  MAKE_FLAGS += V=1
+endif
+
+define Build/Configure
+	rm -f $(PKG_BUILD_DIR)/.config
+	touch $(PKG_BUILD_DIR)/.config
+ifeq ($(DEVICE_TYPE),nas)
+	echo "CONFIG_HDPARM=y" >> $(PKG_BUILD_DIR)/.config
+endif
+ifeq ($(BUILD_VARIANT),selinux)
+	cat $(TOPDIR)/$(SOURCE)/selinux.config >> $(PKG_BUILD_DIR)/.config
+endif
+	grep 'CONFIG_BUSYBOX_$(BUSYBOX_SYM)' $(TOPDIR)/.config | sed -e "s,\\(# \)\\?CONFIG_BUSYBOX_$(BUSYBOX_SYM)_\\(.*\\),\\1CONFIG_\\2,g" >> $(PKG_BUILD_DIR)/.config
+	yes 'n' | $(MAKE) -C $(PKG_BUILD_DIR) $(MAKE_FLAGS) oldconfig
+endef
+
+define Build/Compile
+	$(call Build/Compile/Default, \
+		CONFIG_PREFIX="$(PKG_INSTALL_DIR)" \
+		all install \
+	)
+endef
+
+define Package/busybox/install
+	$(INSTALL_DIR) $(1)/etc/init.d
+	$(INSTALL_DIR) $(1)/usr/sbin
+	$(CP) $(PKG_INSTALL_DIR)/* $(1)/
+ifneq ($(CONFIG_BUSYBOX_$(BUSYBOX_SYM)_FEATURE_SYSLOG)$(CONFIG_BUSYBOX_$(BUSYBOX_SYM)_FEATURE_SYSLOGD_CFG),)
+	touch $(1)/etc/syslog.conf
+endif
+ifneq ($(CONFIG_BUSYBOX_$(BUSYBOX_SYM)_CROND),)
+	$(INSTALL_BIN) ./files/cron $(1)/etc/init.d/cron
+	$(INSTALL_DIR) $(1)/etc/crontabs
+endif
+ifneq ($(CONFIG_BUSYBOX_$(BUSYBOX_SYM)_NTPD),)
+	$(INSTALL_BIN) ./files/sysntpd $(1)/etc/init.d/sysntpd
+	$(INSTALL_BIN) ./files/ntpd-hotplug $(1)/usr/sbin/ntpd-hotplug
+	$(INSTALL_DIR) $(1)/etc/capabilities $(1)/usr/share/acl.d
+	$(INSTALL_DATA) ./files/ntpd.capabilities $(1)/etc/capabilities/ntpd.json
+	$(INSTALL_DATA) ./files/ntpd_acl.json $(1)/usr/share/acl.d/ntpd.json
+endif
+	-rm -rf $(1)/lib64
+endef
+
+Package/busybox-selinux/install = $(Package/busybox/install)
+
+$(eval $(call BuildPackage,busybox))
+$(eval $(call BuildPackage,busybox-selinux))
diff --git a/package/utils/busybox/config/Config.in b/package/utils/busybox/config/Config.in
new file mode 100644
index 0000000..f306298
--- /dev/null
+++ b/package/utils/busybox/config/Config.in
@@ -0,0 +1,741 @@
+#
+# For a description of the syntax of this configuration file,
+# see docs/Kconfig-language.txt.
+#
+
+
+config BUSYBOX_CONFIG_HAVE_DOT_CONFIG
+	bool
+	default BUSYBOX_DEFAULT_HAVE_DOT_CONFIG
+
+menu "Settings"
+
+config BUSYBOX_CONFIG_DESKTOP
+	bool "Enable compatibility for full-blown desktop systems (8kb)"
+	default BUSYBOX_DEFAULT_DESKTOP
+	help
+	Enable applet options and features which are not essential.
+	Many applet options have dedicated config options to (de)select them
+	under that applet; this options enables those options which have no
+	individual config item for them.
+
+	Select this if you plan to use busybox on full-blown desktop machine
+	with common Linux distro, which needs higher level of command-line
+	compatibility.
+
+	If you are preparing your build to be used on an embedded box
+	where you have tighter control over the entire set of userspace
+	tools, you can unselect this option for smaller code size.
+
+config BUSYBOX_CONFIG_EXTRA_COMPAT
+	bool "Provide compatible behavior for rare corner cases (bigger code)"
+	default BUSYBOX_DEFAULT_EXTRA_COMPAT
+	help
+	This option makes grep, sed etc handle rare corner cases
+	(embedded NUL bytes and such). This makes code bigger and uses
+	some GNU extensions in libc. You probably only need this option
+	if you plan to run busybox on desktop.
+
+config BUSYBOX_CONFIG_FEDORA_COMPAT
+	bool "Building for Fedora distribution"
+	default BUSYBOX_DEFAULT_FEDORA_COMPAT
+	help
+	This option makes some tools behave like they do on Fedora.
+
+	At the time of this writing (2017-08) this only affects uname:
+	normally, uname -p (processor) and uname -i (platform)
+	are shown as "unknown", but with this option uname -p
+	shows the same string as uname -m (machine type),
+	and so does uname -i unless machine type is i486/i586/i686 -
+	then uname -i shows "i386".
+
+config BUSYBOX_CONFIG_INCLUDE_SUSv2
+	bool "Enable obsolete features removed before SUSv3"
+	default BUSYBOX_DEFAULT_INCLUDE_SUSv2
+	help
+	This option will enable backwards compatibility with SuSv2,
+	specifically, old-style numeric options ('command -1 <file>')
+	will be supported in head, tail, and fold. (Note: should
+	affect renice too.)
+
+config BUSYBOX_CONFIG_LONG_OPTS
+	bool "Support --long-options"
+	default BUSYBOX_DEFAULT_LONG_OPTS
+	help
+	Enable this if you want busybox applets to use the gnu --long-option
+	style, in addition to single character -a -b -c style options.
+
+config BUSYBOX_CONFIG_SHOW_USAGE
+	bool "Show applet usage messages"
+	default BUSYBOX_DEFAULT_SHOW_USAGE
+	help
+	Enabling this option, applets will show terse help messages
+	when invoked with wrong arguments.
+	If you do not want to show any (helpful) usage message when
+	issuing wrong command syntax, you can say 'N' here,
+	saving approximately 7k.
+
+config BUSYBOX_CONFIG_FEATURE_VERBOSE_USAGE
+	bool "Show verbose applet usage messages"
+	default BUSYBOX_DEFAULT_FEATURE_VERBOSE_USAGE
+	depends on BUSYBOX_CONFIG_SHOW_USAGE
+	help
+	All applets will show verbose help messages when invoked with --help.
+	This will add a lot of text to the binary.
+
+config BUSYBOX_CONFIG_FEATURE_COMPRESS_USAGE
+	bool "Store applet usage messages in compressed form"
+	default BUSYBOX_DEFAULT_FEATURE_COMPRESS_USAGE
+	depends on BUSYBOX_CONFIG_SHOW_USAGE
+	help
+	Store usage messages in .bz2 compressed form, uncompress them
+	on-the-fly when "APPLET --help" is run.
+
+	If you have a really tiny busybox with few applets enabled (and
+	bunzip2 isn't one of them), the overhead of the decompressor might
+	be noticeable. Also, if you run executables directly from ROM
+	and have very little memory, this might not be a win. Otherwise,
+	you probably want this.
+
+config BUSYBOX_CONFIG_LFS
+	bool
+	default BUSYBOX_DEFAULT_LFS
+	help
+	If you need to work with large files, enable this option.
+	This will have no effect if your kernel or your C
+	library lacks large file support for large files. Some of the
+	programs that can benefit from large file support include dd, gzip,
+	cp, mount, tar.
+
+config BUSYBOX_CONFIG_PAM
+	bool "Support PAM (Pluggable Authentication Modules)"
+	default BUSYBOX_DEFAULT_PAM
+	help
+	Use PAM in some applets (currently login and httpd) instead
+	of direct access to password database.
+
+config BUSYBOX_CONFIG_FEATURE_DEVPTS
+	bool "Use the devpts filesystem for Unix98 PTYs"
+	default BUSYBOX_DEFAULT_FEATURE_DEVPTS
+	help
+	Enable if you want to use Unix98 PTY support. If enabled,
+	busybox will use /dev/ptmx for the master side of the pseudoterminal
+	and /dev/pts/<number> for the slave side. Otherwise, BSD style
+	/dev/ttyp<number> will be used. To use this option, you should have
+	devpts mounted.
+
+config BUSYBOX_CONFIG_FEATURE_UTMP
+	bool "Support utmp file"
+	default BUSYBOX_DEFAULT_FEATURE_UTMP
+	help
+	The file /var/run/utmp is used to track who is currently logged in.
+	With this option on, certain applets (getty, login, telnetd etc)
+	will create and delete entries there.
+	"who" applet requires this option.
+
+config BUSYBOX_CONFIG_FEATURE_WTMP
+	bool "Support wtmp file"
+	default BUSYBOX_DEFAULT_FEATURE_WTMP
+	depends on BUSYBOX_CONFIG_FEATURE_UTMP
+	help
+	The file /var/run/wtmp is used to track when users have logged into
+	and logged out of the system.
+	With this option on, certain applets (getty, login, telnetd etc)
+	will append new entries there.
+	"last" applet requires this option.
+
+config BUSYBOX_CONFIG_FEATURE_PIDFILE
+	bool "Support writing pidfiles"
+	default BUSYBOX_DEFAULT_FEATURE_PIDFILE
+	help
+	This option makes some applets (e.g. crond, syslogd, inetd) write
+	a pidfile at the configured PID_FILE_PATH.  It has no effect
+	on applets which require pidfiles to run.
+
+config BUSYBOX_CONFIG_PID_FILE_PATH
+	string "Directory for pidfiles"
+	default BUSYBOX_DEFAULT_PID_FILE_PATH
+	depends on BUSYBOX_CONFIG_FEATURE_PIDFILE || BUSYBOX_CONFIG_FEATURE_CROND_SPECIAL_TIMES
+	help
+	This is the default path where pidfiles are created.  Applets which
+	allow you to set the pidfile path on the command line will override
+	this value.  The option has no effect on applets that require you to
+	specify a pidfile path.  When crond has the 'Support special times'
+	option enabled, the 'crond.reboot' file is also stored here.
+
+config BUSYBOX_CONFIG_BUSYBOX
+	bool "Include busybox applet"
+	default BUSYBOX_DEFAULT_BUSYBOX
+	help
+	The busybox applet provides general help message and allows
+	the included applets to be listed.  It also provides
+	optional --install command to create applet links. If you unselect
+	this option, running busybox without any arguments will give
+	just a cryptic error message:
+
+	$ busybox
+	busybox: applet not found
+
+	Running "busybox APPLET [ARGS...]" will still work, of course.
+
+config BUSYBOX_CONFIG_FEATURE_SHOW_SCRIPT
+	bool "Support --show SCRIPT"
+	default BUSYBOX_DEFAULT_FEATURE_SHOW_SCRIPT
+	depends on BUSYBOX_CONFIG_BUSYBOX
+
+config BUSYBOX_CONFIG_FEATURE_INSTALLER
+	bool "Support --install [-s] to install applet links at runtime"
+	default BUSYBOX_DEFAULT_FEATURE_INSTALLER
+	depends on BUSYBOX_CONFIG_BUSYBOX
+	help
+	Enable 'busybox --install [-s]' support. This will allow you to use
+	busybox at runtime to create hard links or symlinks for all the
+	applets that are compiled into busybox.
+
+config BUSYBOX_CONFIG_INSTALL_NO_USR
+	bool "Don't use /usr"
+	default BUSYBOX_DEFAULT_INSTALL_NO_USR
+	help
+	Disable use of /usr. "busybox --install" and "make install"
+	will install applets only to /bin and /sbin,
+	never to /usr/bin or /usr/sbin.
+
+config BUSYBOX_CONFIG_FEATURE_SUID
+	bool "Drop SUID state for most applets"
+	default BUSYBOX_DEFAULT_FEATURE_SUID
+	help
+	With this option you can install the busybox binary belonging
+	to root with the suid bit set, enabling some applets to perform
+	root-level operations even when run by ordinary users
+	(for example, mounting of user mounts in fstab needs this).
+
+	With this option enabled, busybox drops privileges for applets
+	that don't need root access, before entering their main() function.
+
+	If you are really paranoid and don't want even initial busybox code
+	to run under root for every applet, build two busybox binaries with
+	different applets in them (and the appropriate symlinks pointing
+	to each binary), and only set the suid bit on the one that needs it.
+
+	Some applets which require root rights (need suid bit on the binary
+	or to be run by root) and will refuse to execute otherwise:
+	crontab, login, passwd, su, vlock, wall.
+
+	The applets which will use root rights if they have them
+	(via suid bit, or because run by root), but would try to work
+	without root right nevertheless:
+	findfs, ping[6], traceroute[6], mount.
+
+	Note that if you DO NOT select this option, but DO make busybox
+	suid root, ALL applets will run under root, which is a huge
+	security hole (think "cp /some/file /etc/passwd").
+
+config BUSYBOX_CONFIG_FEATURE_SUID_CONFIG
+	bool "Enable SUID configuration via /etc/busybox.conf"
+	default BUSYBOX_DEFAULT_FEATURE_SUID_CONFIG
+	depends on BUSYBOX_CONFIG_FEATURE_SUID
+	help
+	Allow the SUID/SGID state of an applet to be determined at runtime
+	by checking /etc/busybox.conf. (This is sort of a poor man's sudo.)
+	The format of this file is as follows:
+
+	APPLET = [Ssx-][Ssx-][x-] [USER.GROUP]
+
+	s: USER or GROUP is allowed to execute APPLET.
+	   APPLET will run under USER or GROUP
+	   (regardless of who's running it).
+	S: USER or GROUP is NOT allowed to execute APPLET.
+	   APPLET will run under USER or GROUP.
+	   This option is not very sensical.
+	x: USER/GROUP/others are allowed to execute APPLET.
+	   No UID/GID change will be done when it is run.
+	-: USER/GROUP/others are not allowed to execute APPLET.
+
+	An example might help:
+
+	|[SUID]
+	|su = ssx root.0 # applet su can be run by anyone and runs with
+	|                # euid=0,egid=0
+	|su = ssx        # exactly the same
+	|
+	|mount = sx- root.disk # applet mount can be run by root and members
+	|                      # of group disk (but not anyone else)
+	|                      # and runs with euid=0 (egid is not changed)
+	|
+	|cp = --- # disable applet cp for everyone
+
+	The file has to be owned by user root, group root and has to be
+	writeable only by root:
+		(chown 0.0 /etc/busybox.conf; chmod 600 /etc/busybox.conf)
+	The busybox executable has to be owned by user root, group
+	root and has to be setuid root for this to work:
+		(chown 0.0 /bin/busybox; chmod 4755 /bin/busybox)
+
+	Robert 'sandman' Griebl has more information here:
+	<url: http://www.softforge.de/bb/suid.html >.
+
+config BUSYBOX_CONFIG_FEATURE_SUID_CONFIG_QUIET
+	bool "Suppress warning message if /etc/busybox.conf is not readable"
+	default BUSYBOX_DEFAULT_FEATURE_SUID_CONFIG_QUIET
+	depends on BUSYBOX_CONFIG_FEATURE_SUID_CONFIG
+	help
+	/etc/busybox.conf should be readable by the user needing the SUID,
+	check this option to avoid users to be notified about missing
+	permissions.
+
+config BUSYBOX_CONFIG_FEATURE_PREFER_APPLETS
+	bool "exec prefers applets"
+	default BUSYBOX_DEFAULT_FEATURE_PREFER_APPLETS
+	help
+	This is an experimental option which directs applets about to
+	call 'exec' to try and find an applicable busybox applet before
+	searching the PATH. This is typically done by exec'ing
+	/proc/self/exe.
+
+	This may affect shell, find -exec, xargs and similar applets.
+	They will use applets even if /bin/APPLET -> busybox link
+	is missing (or is not a link to busybox). However, this causes
+	problems in chroot jails without mounted /proc and with ps/top
+	(command name can be shown as 'exe' for applets started this way).
+
+config BUSYBOX_CONFIG_BUSYBOX_EXEC_PATH
+	string "Path to busybox executable"
+	default BUSYBOX_DEFAULT_BUSYBOX_EXEC_PATH
+	help
+	When applets need to run other applets, busybox
+	sometimes needs to exec() itself. When the /proc filesystem is
+	mounted, /proc/self/exe always points to the currently running
+	executable. If you haven't got /proc, set this to wherever you
+	want to run busybox from.
+
+config BUSYBOX_CONFIG_SELINUX
+	bool "Support NSA Security Enhanced Linux"
+	default BUSYBOX_DEFAULT_SELINUX
+	help
+	Enable support for SELinux in applets ls, ps, and id. Also provide
+	the option of compiling in SELinux applets.
+
+	If you do not have a complete SELinux userland installed, this stuff
+	will not compile.  Specifially, libselinux 1.28 or better is
+	directly required by busybox. If the installation is located in a
+	non-standard directory, provide it by invoking make as follows:
+
+		CFLAGS=-I<libselinux-include-path> \
+		LDFLAGS=-L<libselinux-lib-path> \
+		make
+
+	Most people will leave this set to 'N'.
+
+config BUSYBOX_CONFIG_FEATURE_CLEAN_UP
+	bool "Clean up all memory before exiting (usually not needed)"
+	default BUSYBOX_DEFAULT_FEATURE_CLEAN_UP
+	help
+	As a size optimization, busybox normally exits without explicitly
+	freeing dynamically allocated memory or closing files. This saves
+	space since the OS will clean up for us, but it can confuse debuggers
+	like valgrind, which report tons of memory and resource leaks.
+
+	Don't enable this unless you have a really good reason to clean
+	things up manually.
+
+config BUSYBOX_CONFIG_FEATURE_SYSLOG_INFO
+	bool "Support LOG_INFO level syslog messages"
+	default BUSYBOX_DEFAULT_FEATURE_SYSLOG_INFO
+	depends on BUSYBOX_CONFIG_FEATURE_SYSLOG
+	help
+	Applets which send their output to syslog use either LOG_INFO or
+	LOG_ERR log levels, but by disabling this option all messages will
+	be logged at the LOG_ERR level, saving just under 200 bytes.
+
+# These are auto-selected by other options
+
+config BUSYBOX_CONFIG_FEATURE_SYSLOG
+	bool #No description makes it a hidden option
+	default BUSYBOX_DEFAULT_FEATURE_SYSLOG
+	#help
+	#This option is auto-selected when you select any applet which may
+	#send its output to syslog. You do not need to select it manually.
+
+comment 'Build Options'
+
+config BUSYBOX_CONFIG_STATIC
+	bool "Build static binary (no shared libs)"
+	default BUSYBOX_DEFAULT_STATIC
+	help
+	If you want to build a static binary, which does not use
+	or require any shared libraries, enable this option.
+	Static binaries are larger, but do not require functioning
+	dynamic libraries to be present, which is important if used
+	as a system rescue tool.
+
+config BUSYBOX_CONFIG_PIE
+	bool "Build position independent executable"
+	default BUSYBOX_DEFAULT_PIE
+	depends on !BUSYBOX_CONFIG_STATIC
+	help
+	Hardened code option. PIE binaries are loaded at a different
+	address at each invocation. This has some overhead,
+	particularly on x86-32 which is short on registers.
+
+	Most people will leave this set to 'N'.
+
+config BUSYBOX_CONFIG_NOMMU
+	bool "Force NOMMU build"
+	default BUSYBOX_DEFAULT_NOMMU
+	help
+	Busybox tries to detect whether architecture it is being
+	built against supports MMU or not. If this detection fails,
+	or if you want to build NOMMU version of busybox for testing,
+	you may force NOMMU build here.
+
+	Most people will leave this set to 'N'.
+
+# PIE can be made to work with BUILD_LIBBUSYBOX, but currently
+# build system does not support that
+config BUSYBOX_CONFIG_BUILD_LIBBUSYBOX
+	bool "Build shared libbusybox"
+	default BUSYBOX_DEFAULT_BUILD_LIBBUSYBOX
+	depends on !BUSYBOX_CONFIG_FEATURE_PREFER_APPLETS && !BUSYBOX_CONFIG_PIE && !BUSYBOX_CONFIG_STATIC
+	help
+	Build a shared library libbusybox.so.N.N.N which contains all
+	busybox code.
+
+	This feature allows every applet to be built as a really tiny
+	separate executable linked against the library:
+	|$ size 0_lib/l*
+	|    text  data   bss     dec    hex filename
+	|     939   212    28    1179    49b 0_lib/last
+	|     939   212    28    1179    49b 0_lib/less
+	|  919138  8328  1556  929022  e2cfe 0_lib/libbusybox.so.1.N.M
+
+	This is useful on NOMMU systems which are not capable
+	of sharing executables, but are capable of sharing code
+	in dynamic libraries.
+
+config BUSYBOX_CONFIG_FEATURE_LIBBUSYBOX_STATIC
+	bool "Pull in all external references into libbusybox"
+	default BUSYBOX_DEFAULT_FEATURE_LIBBUSYBOX_STATIC
+	depends on BUSYBOX_CONFIG_BUILD_LIBBUSYBOX
+	help
+	Make libbusybox library independent, not using or requiring
+	any other shared libraries.
+
+config BUSYBOX_CONFIG_FEATURE_INDIVIDUAL
+	bool "Produce a binary for each applet, linked against libbusybox"
+	default BUSYBOX_DEFAULT_FEATURE_INDIVIDUAL
+	depends on BUSYBOX_CONFIG_BUILD_LIBBUSYBOX
+	help
+	If your CPU architecture doesn't allow for sharing text/rodata
+	sections of running binaries, but allows for runtime dynamic
+	libraries, this option will allow you to reduce memory footprint
+	when you have many different applets running at once.
+
+	If your CPU architecture allows for sharing text/rodata,
+	having single binary is more optimal.
+
+	Each applet will be a tiny program, dynamically linked
+	against libbusybox.so.N.N.N.
+
+	You need to have a working dynamic linker.
+
+config BUSYBOX_CONFIG_FEATURE_SHARED_BUSYBOX
+	bool "Produce additional busybox binary linked against libbusybox"
+	default BUSYBOX_DEFAULT_FEATURE_SHARED_BUSYBOX
+	depends on BUSYBOX_CONFIG_BUILD_LIBBUSYBOX
+	help
+	Build busybox, dynamically linked against libbusybox.so.N.N.N.
+
+	You need to have a working dynamic linker.
+
+### config BUILD_AT_ONCE
+###	bool "Compile all sources at once"
+###	default n
+###	help
+###	Normally each source-file is compiled with one invocation of
+###	the compiler.
+###	If you set this option, all sources are compiled at once.
+###	This gives the compiler more opportunities to optimize which can
+###	result in smaller and/or faster binaries.
+###
+###	Setting this option will consume alot of memory, e.g. if you
+###	enable all applets with all features, gcc uses more than 300MB
+###	RAM during compilation of busybox.
+###
+###	This option is most likely only beneficial for newer compilers
+###	such as gcc-4.1 and above.
+###
+###	Say 'N' unless you know what you are doing.
+
+config BUSYBOX_CONFIG_CROSS_COMPILER_PREFIX
+	string "Cross compiler prefix"
+	default BUSYBOX_DEFAULT_CROSS_COMPILER_PREFIX
+	help
+	If you want to build busybox with a cross compiler, then you
+	will need to set this to the cross-compiler prefix, for example,
+	"i386-uclibc-".
+
+	Note that CROSS_COMPILE environment variable or
+	"make CROSS_COMPILE=xxx ..." will override this selection.
+
+	Native builds leave this empty.
+
+config BUSYBOX_CONFIG_SYSROOT
+	string "Path to sysroot"
+	default BUSYBOX_DEFAULT_SYSROOT
+	help
+	If you want to build busybox with a cross compiler, then you
+	might also need to specify where /usr/include and /usr/lib
+	will be found.
+
+	For example, busybox can be built against an installed
+	Android NDK, platform version 9, for ARM ABI with
+
+	CONFIG_SYSROOT=/opt/android-ndk/platforms/android-9/arch-arm
+
+	Native builds leave this empty.
+
+config BUSYBOX_CONFIG_EXTRA_CFLAGS
+	string "Additional CFLAGS"
+	default BUSYBOX_DEFAULT_EXTRA_CFLAGS
+	help
+	Additional CFLAGS to pass to the compiler verbatim.
+
+config BUSYBOX_CONFIG_EXTRA_LDFLAGS
+	string "Additional LDFLAGS"
+	default BUSYBOX_DEFAULT_EXTRA_LDFLAGS
+	help
+	Additional LDFLAGS to pass to the linker verbatim.
+
+config BUSYBOX_CONFIG_EXTRA_LDLIBS
+	string "Additional LDLIBS"
+	default BUSYBOX_DEFAULT_EXTRA_LDLIBS
+	help
+	Additional LDLIBS to pass to the linker with -l.
+
+config BUSYBOX_CONFIG_USE_PORTABLE_CODE
+	bool "Avoid using GCC-specific code constructs"
+	default BUSYBOX_DEFAULT_USE_PORTABLE_CODE
+	help
+	Use this option if you are trying to compile busybox with
+	compiler other than gcc.
+	If you do use gcc, this option may needlessly increase code size.
+
+config BUSYBOX_CONFIG_STACK_OPTIMIZATION_386
+	bool "Use -mpreferred-stack-boundary=2 on i386 arch"
+	default BUSYBOX_DEFAULT_STACK_OPTIMIZATION_386
+	help
+	This option makes for smaller code, but some libc versions
+	do not work with it (they use SSE instructions without
+	ensuring stack alignment).
+
+config BUSYBOX_CONFIG_STATIC_LIBGCC
+	bool "Use -static-libgcc"
+	default BUSYBOX_DEFAULT_STATIC_LIBGCC
+	help
+	This option instructs gcc to link in a static version of its
+	support library, libgcc. This means that the binary will require
+	one fewer dynamic library at run time.
+
+comment 'Installation Options ("make install" behavior)'
+
+choice
+	prompt "What kind of applet links to install"
+	default BUSYBOX_CONFIG_INSTALL_APPLET_SYMLINKS
+	help
+	Choose what kind of links to applets are created by "make install".
+
+config BUSYBOX_CONFIG_INSTALL_APPLET_SYMLINKS
+	bool "as soft-links"
+	help
+	Install applets as soft-links to the busybox binary. This needs some
+	free inodes on the filesystem, but might help with filesystem
+	generators that can't cope with hard-links.
+
+config BUSYBOX_CONFIG_INSTALL_APPLET_HARDLINKS
+	bool "as hard-links"
+	help
+	Install applets as hard-links to the busybox binary. This might
+	count on a filesystem with few inodes.
+
+config BUSYBOX_CONFIG_INSTALL_APPLET_SCRIPT_WRAPPERS
+	bool "as script wrappers"
+	help
+	Install applets as script wrappers that call the busybox binary.
+
+config BUSYBOX_CONFIG_INSTALL_APPLET_DONT
+	bool "not installed"
+	help
+	Do not install applet links. Useful when you plan to use
+	busybox --install for installing links, or plan to use
+	a standalone shell and thus don't need applet links.
+
+endchoice
+
+choice
+	prompt "/bin/sh applet link"
+	default BUSYBOX_CONFIG_INSTALL_SH_APPLET_SYMLINK
+	depends on BUSYBOX_CONFIG_INSTALL_APPLET_SCRIPT_WRAPPERS
+	help
+	Choose how you install /bin/sh applet link.
+
+config BUSYBOX_CONFIG_INSTALL_SH_APPLET_SYMLINK
+	bool "as soft-link"
+	help
+	Install /bin/sh applet as soft-link to the busybox binary.
+
+config BUSYBOX_CONFIG_INSTALL_SH_APPLET_HARDLINK
+	bool "as hard-link"
+	help
+	Install /bin/sh applet as hard-link to the busybox binary.
+
+config BUSYBOX_CONFIG_INSTALL_SH_APPLET_SCRIPT_WRAPPER
+	bool "as script wrapper"
+	help
+	Install /bin/sh applet as script wrapper that calls
+	the busybox binary.
+
+endchoice
+
+config BUSYBOX_CONFIG_PREFIX
+	string "Destination path for 'make install'"
+	default BUSYBOX_DEFAULT_PREFIX
+	help
+	Where "make install" should install busybox binary and links.
+
+comment 'Debugging Options'
+
+config BUSYBOX_CONFIG_DEBUG
+	bool "Build with debug information"
+	default BUSYBOX_DEFAULT_DEBUG
+	help
+	Say Y here to compile with debug information.
+	This increases the size of the binary considerably, and
+	should only be used when doing development.
+
+	This adds -g option to gcc command line.
+
+	Most people should answer N.
+
+config BUSYBOX_CONFIG_DEBUG_PESSIMIZE
+	bool "Disable compiler optimizations"
+	default BUSYBOX_DEFAULT_DEBUG_PESSIMIZE
+	depends on BUSYBOX_CONFIG_DEBUG
+	help
+	The compiler's optimization of source code can eliminate and reorder
+	code, resulting in an executable that's hard to understand when
+	stepping through it with a debugger. This switches it off, resulting
+	in a much bigger executable that more closely matches the source
+	code.
+
+	This replaces -Os/-O2 with -O0 in gcc command line.
+
+config BUSYBOX_CONFIG_DEBUG_SANITIZE
+	bool "Enable runtime sanitizers (ASAN/LSAN/USAN/etc...)"
+	default BUSYBOX_DEFAULT_DEBUG_SANITIZE
+	help
+	Say Y here if you want to enable runtime sanitizers. These help
+	catch bad memory accesses (e.g. buffer overflows), but will make
+	the executable larger and slow down runtime a bit.
+
+	This adds -fsanitize=foo options to gcc command line.
+
+	If you aren't developing/testing busybox, say N here.
+
+config BUSYBOX_CONFIG_UNIT_TEST
+	bool "Build unit tests"
+	default BUSYBOX_DEFAULT_UNIT_TEST
+	help
+	Say Y here if you want to build unit tests (both the framework and
+	test cases) as an applet. This results in bigger code, so you
+	probably don't want this option in production builds.
+
+config BUSYBOX_CONFIG_WERROR
+	bool "Abort compilation on any warning"
+	default BUSYBOX_DEFAULT_WERROR
+	help
+	This adds -Werror to gcc command line.
+
+	Most people should answer N.
+
+config BUSYBOX_CONFIG_WARN_SIMPLE_MSG
+	bool "Warn about single parameter bb_xx_msg calls"
+	default BUSYBOX_DEFAULT_WARN_SIMPLE_MSG
+	help
+	This will cause warnings to be shown for any instances of
+	bb_error_msg(), bb_error_msg_and_die(), bb_perror_msg(),
+	bb_perror_msg_and_die(), bb_herror_msg() or bb_herror_msg_and_die()
+	being called with a single parameter. In these cases the equivalent
+	bb_simple_xx_msg function should be used instead.
+	Note that use of STRERROR_FMT may give false positives.
+
+	If you aren't developing busybox, say N here.
+
+choice
+	prompt "Additional debugging library"
+	default BUSYBOX_CONFIG_NO_DEBUG_LIB
+	help
+	Using an additional debugging library will make busybox become
+	considerably larger and will cause it to run more slowly. You
+	should always leave this option disabled for production use.
+
+	dmalloc support:
+	----------------
+	This enables compiling with dmalloc ( http://dmalloc.com/ )
+	which is an excellent public domain mem leak and malloc problem
+	detector. To enable dmalloc, before running busybox you will
+	want to properly set your environment, for example:
+		export DMALLOC_OPTIONS=debug=0x34f47d83,inter=100,log=logfile
+	The 'debug=' value is generated using the following command
+	dmalloc -p log-stats -p log-non-free -p log-bad-space \
+		-p log-elapsed-time -p check-fence -p check-heap \
+		-p check-lists -p check-blank -p check-funcs -p realloc-copy \
+		-p allow-free-null
+
+	Electric-fence support:
+	-----------------------
+	This enables compiling with Electric-fence support. Electric
+	fence is another very useful malloc debugging library which uses
+	your computer's virtual memory hardware to detect illegal memory
+	accesses. This support will make busybox be considerably larger
+	and run slower, so you should leave this option disabled unless
+	you are hunting a hard to find memory problem.
+
+
+config BUSYBOX_CONFIG_NO_DEBUG_LIB
+	bool "None"
+
+config BUSYBOX_CONFIG_DMALLOC
+	bool "Dmalloc"
+
+config BUSYBOX_CONFIG_EFENCE
+	bool "Electric-fence"
+
+endchoice
+
+source "libbb/Config.in"
+
+endmenu
+
+comment "Applets"
+
+source "archival/Config.in"
+source "coreutils/Config.in"
+source "console-tools/Config.in"
+source "debianutils/Config.in"
+source "klibc-utils/Config.in"
+source "editors/Config.in"
+source "findutils/Config.in"
+source "init/Config.in"
+source "loginutils/Config.in"
+source "e2fsprogs/Config.in"
+source "modutils/Config.in"
+source "util-linux/Config.in"
+source "miscutils/Config.in"
+source "networking/Config.in"
+source "printutils/Config.in"
+source "mailutils/Config.in"
+source "procps/Config.in"
+source "runit/Config.in"
+source "selinux/Config.in"
+source "shell/Config.in"
+source "sysklogd/Config.in"
diff --git a/package/utils/busybox/config/archival/Config.in b/package/utils/busybox/config/archival/Config.in
new file mode 100644
index 0000000..ac2b3d2
--- /dev/null
+++ b/package/utils/busybox/config/archival/Config.in
@@ -0,0 +1,450 @@
+# DO NOT EDIT. This file is generated from Config.src
+#
+# For a description of the syntax of this configuration file,
+# see docs/Kconfig-language.txt.
+#
+
+menu "Archival Utilities"
+
+config BUSYBOX_CONFIG_FEATURE_SEAMLESS_XZ
+	bool "Make tar, rpm, modprobe etc understand .xz data"
+	default BUSYBOX_DEFAULT_FEATURE_SEAMLESS_XZ
+
+config BUSYBOX_CONFIG_FEATURE_SEAMLESS_LZMA
+	bool "Make tar, rpm, modprobe etc understand .lzma data"
+	default BUSYBOX_DEFAULT_FEATURE_SEAMLESS_LZMA
+
+config BUSYBOX_CONFIG_FEATURE_SEAMLESS_BZ2
+	bool "Make tar, rpm, modprobe etc understand .bz2 data"
+	default BUSYBOX_DEFAULT_FEATURE_SEAMLESS_BZ2
+
+config BUSYBOX_CONFIG_FEATURE_SEAMLESS_GZ
+	bool "Make tar, rpm, modprobe etc understand .gz data"
+	default BUSYBOX_DEFAULT_FEATURE_SEAMLESS_GZ
+
+config BUSYBOX_CONFIG_FEATURE_SEAMLESS_Z
+	bool "Make tar, rpm, modprobe etc understand .Z data"
+	default BUSYBOX_DEFAULT_FEATURE_SEAMLESS_Z  # it is ancient
+
+config BUSYBOX_CONFIG_AR
+	bool "ar (9.5 kb)"
+	default BUSYBOX_DEFAULT_AR  # needs to be improved to be able to replace binutils ar
+	help
+	ar is an archival utility program used to create, modify, and
+	extract contents from archives. In practice, it is used exclusively
+	for object module archives used by compilers.
+
+	Unless you have a specific application which requires ar, you should
+	probably say N here: most compilers come with their own ar utility.
+
+config BUSYBOX_CONFIG_FEATURE_AR_LONG_FILENAMES
+	bool "Support long filenames (not needed for debs)"
+	default BUSYBOX_DEFAULT_FEATURE_AR_LONG_FILENAMES
+	depends on BUSYBOX_CONFIG_AR
+	help
+	By default the ar format can only store the first 15 characters
+	of the filename, this option removes that limitation.
+	It supports the GNU ar long filename method which moves multiple long
+	filenames into a the data section of a new ar entry.
+
+config BUSYBOX_CONFIG_FEATURE_AR_CREATE
+	bool "Support archive creation"
+	default BUSYBOX_DEFAULT_FEATURE_AR_CREATE
+	depends on BUSYBOX_CONFIG_AR
+	help
+	This enables archive creation (-c and -r) with busybox ar.
+config BUSYBOX_CONFIG_UNCOMPRESS
+	bool "uncompress (7.1 kb)"
+	default BUSYBOX_DEFAULT_UNCOMPRESS  # ancient
+	help
+	uncompress is used to decompress archives created by compress.
+	Not much used anymore, replaced by gzip/gunzip.
+config BUSYBOX_CONFIG_GUNZIP
+	bool "gunzip (11 kb)"
+	default BUSYBOX_DEFAULT_GUNZIP
+	select BUSYBOX_CONFIG_FEATURE_GZIP_DECOMPRESS
+	help
+	gunzip is used to decompress archives created by gzip.
+	You can use the '-t' option to test the integrity of
+	an archive, without decompressing it.
+
+config BUSYBOX_CONFIG_ZCAT
+	bool "zcat (24 kb)"
+	default BUSYBOX_DEFAULT_ZCAT
+	select BUSYBOX_CONFIG_FEATURE_GZIP_DECOMPRESS
+	help
+	Alias to "gunzip -c".
+
+config BUSYBOX_CONFIG_FEATURE_GUNZIP_LONG_OPTIONS
+	bool "Enable long options"
+	default BUSYBOX_DEFAULT_FEATURE_GUNZIP_LONG_OPTIONS
+	depends on (BUSYBOX_CONFIG_GUNZIP || BUSYBOX_CONFIG_ZCAT) && BUSYBOX_CONFIG_LONG_OPTS
+config BUSYBOX_CONFIG_BUNZIP2
+	bool "bunzip2 (8.7 kb)"
+	default BUSYBOX_DEFAULT_BUNZIP2
+	select BUSYBOX_CONFIG_FEATURE_BZIP2_DECOMPRESS
+	help
+	bunzip2 is a compression utility using the Burrows-Wheeler block
+	sorting text compression algorithm, and Huffman coding. Compression
+	is generally considerably better than that achieved by more
+	conventional LZ77/LZ78-based compressors, and approaches the
+	performance of the PPM family of statistical compressors.
+
+	Unless you have a specific application which requires bunzip2, you
+	should probably say N here.
+
+config BUSYBOX_CONFIG_BZCAT
+	bool "bzcat (8.7 kb)"
+	default BUSYBOX_DEFAULT_BZCAT
+	select BUSYBOX_CONFIG_FEATURE_BZIP2_DECOMPRESS
+	help
+	Alias to "bunzip2 -c".
+config BUSYBOX_CONFIG_UNLZMA
+	bool "unlzma (7.5 kb)"
+	default BUSYBOX_DEFAULT_UNLZMA
+	help
+	unlzma is a compression utility using the Lempel-Ziv-Markov chain
+	compression algorithm, and range coding. Compression
+	is generally considerably better than that achieved by the bzip2
+	compressors.
+
+config BUSYBOX_CONFIG_LZCAT
+	bool "lzcat (7.5 kb)"
+	default BUSYBOX_DEFAULT_LZCAT
+	help
+	Alias to "unlzma -c".
+
+config BUSYBOX_CONFIG_LZMA
+	bool "lzma -d"
+	default BUSYBOX_DEFAULT_LZMA
+	help
+	Enable this option if you want commands like "lzma -d" to work.
+	IOW: you'll get lzma applet, but it will always require -d option.
+config BUSYBOX_CONFIG_UNXZ
+	bool "unxz (13 kb)"
+	default BUSYBOX_DEFAULT_UNXZ
+	help
+	unxz is a unlzma successor.
+
+config BUSYBOX_CONFIG_XZCAT
+	bool "xzcat (13 kb)"
+	default BUSYBOX_DEFAULT_XZCAT
+	help
+	Alias to "unxz -c".
+
+config BUSYBOX_CONFIG_XZ
+	bool "xz -d"
+	default BUSYBOX_DEFAULT_XZ
+	help
+	Enable this option if you want commands like "xz -d" to work.
+	IOW: you'll get xz applet, but it will always require -d option.
+config BUSYBOX_CONFIG_BZIP2
+	bool "bzip2 (16 kb)"
+	default BUSYBOX_DEFAULT_BZIP2
+	help
+	bzip2 is a compression utility using the Burrows-Wheeler block
+	sorting text compression algorithm, and Huffman coding. Compression
+	is generally considerably better than that achieved by more
+	conventional LZ77/LZ78-based compressors, and approaches the
+	performance of the PPM family of statistical compressors.
+
+	Unless you have a specific application which requires bzip2, you
+	should probably say N here.
+
+config BUSYBOX_CONFIG_BZIP2_SMALL
+	int "Trade bytes for speed (0:fast, 9:small)"
+	default BUSYBOX_DEFAULT_BZIP2_SMALL  # all "fast or small" options default to small
+	range 0 9
+	depends on BUSYBOX_CONFIG_BZIP2
+	help
+	Trade code size versus speed.
+	Approximate values with gcc-6.3.0 "bzip -9" compressing
+	linux-4.15.tar were:
+	value         time (sec)  code size (386)
+	9 (smallest)       70.11             7687
+	8                  67.93             8091
+	7                  67.88             8405
+	6                  67.78             8624
+	5                  67.05             9427
+	4-0 (fastest)      64.14            12083
+
+config BUSYBOX_CONFIG_FEATURE_BZIP2_DECOMPRESS
+	bool "Enable decompression"
+	default BUSYBOX_DEFAULT_FEATURE_BZIP2_DECOMPRESS
+	depends on BUSYBOX_CONFIG_BZIP2 || BUSYBOX_CONFIG_BUNZIP2 || BUSYBOX_CONFIG_BZCAT
+	help
+	Enable -d (--decompress) and -t (--test) options for bzip2.
+	This will be automatically selected if bunzip2 or bzcat is
+	enabled.
+config BUSYBOX_CONFIG_CPIO
+	bool "cpio (15 kb)"
+	default BUSYBOX_DEFAULT_CPIO
+	help
+	cpio is an archival utility program used to create, modify, and
+	extract contents from archives.
+	cpio has 110 bytes of overheads for every stored file.
+
+	This implementation of cpio can extract cpio archives created in the
+	"newc" or "crc" format.
+
+	Unless you have a specific application which requires cpio, you
+	should probably say N here.
+
+config BUSYBOX_CONFIG_FEATURE_CPIO_O
+	bool "Support archive creation"
+	default BUSYBOX_DEFAULT_FEATURE_CPIO_O
+	depends on BUSYBOX_CONFIG_CPIO
+	help
+	This implementation of cpio can create cpio archives in the "newc"
+	format only.
+
+config BUSYBOX_CONFIG_FEATURE_CPIO_P
+	bool "Support passthrough mode"
+	default BUSYBOX_DEFAULT_FEATURE_CPIO_P
+	depends on BUSYBOX_CONFIG_FEATURE_CPIO_O
+	help
+	Passthrough mode. Rarely used.
+
+config BUSYBOX_CONFIG_FEATURE_CPIO_IGNORE_DEVNO
+	bool "Support --ignore-devno like GNU cpio"
+	default BUSYBOX_DEFAULT_FEATURE_CPIO_IGNORE_DEVNO
+	depends on BUSYBOX_CONFIG_FEATURE_CPIO_O && BUSYBOX_CONFIG_LONG_OPTS
+	help
+	Optionally ignore device numbers when creating archives.
+
+config BUSYBOX_CONFIG_FEATURE_CPIO_RENUMBER_INODES
+	bool "Support --renumber-inodes like GNU cpio"
+	default BUSYBOX_DEFAULT_FEATURE_CPIO_RENUMBER_INODES
+	depends on BUSYBOX_CONFIG_FEATURE_CPIO_O && BUSYBOX_CONFIG_LONG_OPTS
+	help
+	Optionally renumber inodes when creating archives.
+config BUSYBOX_CONFIG_DPKG
+	bool "dpkg (43 kb)"
+	default BUSYBOX_DEFAULT_DPKG
+	select BUSYBOX_CONFIG_FEATURE_SEAMLESS_GZ
+	help
+	dpkg is a medium-level tool to install, build, remove and manage
+	Debian packages.
+
+	This implementation of dpkg has a number of limitations,
+	you should use the official dpkg if possible.
+config BUSYBOX_CONFIG_DPKG_DEB
+	bool "dpkg-deb (30 kb)"
+	default BUSYBOX_DEFAULT_DPKG_DEB
+	select BUSYBOX_CONFIG_FEATURE_SEAMLESS_GZ
+	help
+	dpkg-deb unpacks and provides information about Debian archives.
+
+	This implementation of dpkg-deb cannot pack archives.
+
+	Unless you have a specific application which requires dpkg-deb,
+	say N here.
+config BUSYBOX_CONFIG_GZIP
+	bool "gzip (17 kb)"
+	default BUSYBOX_DEFAULT_GZIP
+	help
+	gzip is used to compress files.
+	It's probably the most widely used UNIX compression program.
+
+config BUSYBOX_CONFIG_FEATURE_GZIP_LONG_OPTIONS
+	bool "Enable long options"
+	default BUSYBOX_DEFAULT_FEATURE_GZIP_LONG_OPTIONS
+	depends on BUSYBOX_CONFIG_GZIP && BUSYBOX_CONFIG_LONG_OPTS
+
+config BUSYBOX_CONFIG_GZIP_FAST
+	int "Trade memory for speed (0:small,slow - 2:fast,big)"
+	default BUSYBOX_DEFAULT_GZIP_FAST
+	range 0 2
+	depends on BUSYBOX_CONFIG_GZIP
+	help
+	Enable big memory options for gzip.
+	0: small buffers, small hash-tables
+	1: larger buffers, larger hash-tables
+	2: larger buffers, largest hash-tables
+	Larger models may give slightly better compression
+
+config BUSYBOX_CONFIG_FEATURE_GZIP_LEVELS
+	bool "Enable compression levels"
+	default BUSYBOX_DEFAULT_FEATURE_GZIP_LEVELS
+	depends on BUSYBOX_CONFIG_GZIP
+	help
+	Enable support for compression levels 4-9. The default level
+	is 6. If levels 1-3 are specified, 4 is used.
+	If this option is not selected, -N options are ignored and -6
+	is used.
+
+config BUSYBOX_CONFIG_FEATURE_GZIP_DECOMPRESS
+	bool "Enable decompression"
+	default BUSYBOX_DEFAULT_FEATURE_GZIP_DECOMPRESS
+	depends on BUSYBOX_CONFIG_GZIP || BUSYBOX_CONFIG_GUNZIP || BUSYBOX_CONFIG_ZCAT
+	help
+	Enable -d (--decompress) and -t (--test) options for gzip.
+	This will be automatically selected if gunzip or zcat is
+	enabled.
+config BUSYBOX_CONFIG_LZOP
+	bool "lzop (12 kb)"
+	default BUSYBOX_DEFAULT_LZOP
+	help
+	Lzop compression/decompresion.
+
+config BUSYBOX_CONFIG_UNLZOP
+	bool "unlzop (13 kb)"
+	default BUSYBOX_DEFAULT_UNLZOP  # INCOMPAT: upstream lzop does not provide such tool
+	help
+	Lzop decompresion.
+
+config BUSYBOX_CONFIG_LZOPCAT
+	bool "lzopcat (13 kb)"
+	default BUSYBOX_DEFAULT_LZOPCAT  # INCOMPAT: upstream lzop does not provide such tool
+	help
+	Alias to "lzop -dc".
+
+config BUSYBOX_CONFIG_LZOP_COMPR_HIGH
+	bool "lzop compression levels 7,8,9 (not very useful)"
+	default BUSYBOX_DEFAULT_LZOP_COMPR_HIGH
+	depends on BUSYBOX_CONFIG_LZOP || BUSYBOX_CONFIG_UNLZOP || BUSYBOX_CONFIG_LZOPCAT
+	help
+	High levels (7,8,9) of lzop compression. These levels
+	are actually slower than gzip at equivalent compression ratios
+	and take up 3.2K of code.
+config BUSYBOX_CONFIG_RPM
+	bool "rpm (32 kb)"
+	default BUSYBOX_DEFAULT_RPM
+	help
+	Mini RPM applet - queries and extracts RPM packages.
+config BUSYBOX_CONFIG_RPM2CPIO
+	bool "rpm2cpio (21 kb)"
+	default BUSYBOX_DEFAULT_RPM2CPIO
+	help
+	Converts a RPM file into a CPIO archive.
+config BUSYBOX_CONFIG_TAR
+	bool "tar (39 kb)"
+	default BUSYBOX_DEFAULT_TAR
+	help
+	tar is an archiving program. It's commonly used with gzip to
+	create compressed archives. It's probably the most widely used
+	UNIX archive program.
+
+config BUSYBOX_CONFIG_FEATURE_TAR_LONG_OPTIONS
+	bool "Enable long options"
+	default BUSYBOX_DEFAULT_FEATURE_TAR_LONG_OPTIONS
+	depends on BUSYBOX_CONFIG_TAR && BUSYBOX_CONFIG_LONG_OPTS
+
+config BUSYBOX_CONFIG_FEATURE_TAR_CREATE
+	bool "Enable -c (archive creation)"
+	default BUSYBOX_DEFAULT_FEATURE_TAR_CREATE
+	depends on BUSYBOX_CONFIG_TAR
+
+config BUSYBOX_CONFIG_FEATURE_TAR_AUTODETECT
+	bool "Autodetect compressed tarballs"
+	default BUSYBOX_DEFAULT_FEATURE_TAR_AUTODETECT
+	depends on BUSYBOX_CONFIG_TAR && (BUSYBOX_CONFIG_FEATURE_SEAMLESS_Z || BUSYBOX_CONFIG_FEATURE_SEAMLESS_GZ || BUSYBOX_CONFIG_FEATURE_SEAMLESS_BZ2 || BUSYBOX_CONFIG_FEATURE_SEAMLESS_LZMA || BUSYBOX_CONFIG_FEATURE_SEAMLESS_XZ)
+	help
+	With this option tar can automatically detect compressed
+	tarballs. Currently it works only on files (not pipes etc).
+
+config BUSYBOX_CONFIG_FEATURE_TAR_FROM
+	bool "Enable -X (exclude from) and -T (include from) options"
+	default BUSYBOX_DEFAULT_FEATURE_TAR_FROM
+	depends on BUSYBOX_CONFIG_TAR
+	help
+	If you enable this option you'll be able to specify
+	a list of files to include or exclude from an archive.
+
+config BUSYBOX_CONFIG_FEATURE_TAR_OLDGNU_COMPATIBILITY
+	bool "Support old tar header format"
+	default BUSYBOX_DEFAULT_FEATURE_TAR_OLDGNU_COMPATIBILITY
+	depends on BUSYBOX_CONFIG_TAR || BUSYBOX_CONFIG_DPKG
+	help
+	This option is required to unpack archives created in
+	the old GNU format; help to kill this old format by
+	repacking your ancient archives with the new format.
+
+config BUSYBOX_CONFIG_FEATURE_TAR_OLDSUN_COMPATIBILITY
+	bool "Enable untarring of tarballs with checksums produced by buggy Sun tar"
+	default BUSYBOX_DEFAULT_FEATURE_TAR_OLDSUN_COMPATIBILITY
+	depends on BUSYBOX_CONFIG_TAR || BUSYBOX_CONFIG_DPKG
+	help
+	This option is required to unpack archives created by some old
+	version of Sun's tar (it was calculating checksum using signed
+	arithmetic). It is said to be fixed in newer Sun tar, but "old"
+	tarballs still exist.
+
+config BUSYBOX_CONFIG_FEATURE_TAR_GNU_EXTENSIONS
+	bool "Support GNU tar extensions (long filenames)"
+	default BUSYBOX_DEFAULT_FEATURE_TAR_GNU_EXTENSIONS
+	depends on BUSYBOX_CONFIG_TAR || BUSYBOX_CONFIG_DPKG
+
+config BUSYBOX_CONFIG_FEATURE_TAR_TO_COMMAND
+	bool "Support writing to an external program (--to-command)"
+	default BUSYBOX_DEFAULT_FEATURE_TAR_TO_COMMAND
+	depends on BUSYBOX_CONFIG_TAR && BUSYBOX_CONFIG_FEATURE_TAR_LONG_OPTIONS
+	help
+	If you enable this option you'll be able to instruct tar to send
+	the contents of each extracted file to the standard input of an
+	external program.
+
+config BUSYBOX_CONFIG_FEATURE_TAR_UNAME_GNAME
+	bool "Enable use of user and group names"
+	default BUSYBOX_DEFAULT_FEATURE_TAR_UNAME_GNAME
+	depends on BUSYBOX_CONFIG_TAR
+	help
+	Enable use of user and group names in tar. This affects contents
+	listings (-t) and preserving permissions when unpacking (-p).
+	+200 bytes.
+
+config BUSYBOX_CONFIG_FEATURE_TAR_NOPRESERVE_TIME
+	bool "Enable -m (do not preserve time) GNU option"
+	default BUSYBOX_DEFAULT_FEATURE_TAR_NOPRESERVE_TIME
+	depends on BUSYBOX_CONFIG_TAR
+
+config BUSYBOX_CONFIG_FEATURE_TAR_SELINUX
+	bool "Support extracting SELinux labels"
+	default BUSYBOX_DEFAULT_FEATURE_TAR_SELINUX
+	depends on BUSYBOX_CONFIG_TAR && BUSYBOX_CONFIG_SELINUX
+	help
+	With this option busybox supports restoring SELinux labels
+	when extracting files from tar archives.
+config BUSYBOX_CONFIG_UNZIP
+	bool "unzip (26 kb)"
+	default BUSYBOX_DEFAULT_UNZIP
+	help
+	unzip will list or extract files from a ZIP archive,
+	commonly found on DOS/WIN systems. The default behavior
+	(with no options) is to extract the archive into the
+	current directory.
+
+config BUSYBOX_CONFIG_FEATURE_UNZIP_CDF
+	bool "Read and use Central Directory data"
+	default BUSYBOX_DEFAULT_FEATURE_UNZIP_CDF
+	depends on BUSYBOX_CONFIG_UNZIP
+	help
+	If you know that you only need to deal with simple
+	ZIP files without deleted/updated files, SFX archives etc,
+	you can reduce code size by unselecting this option.
+	To support less trivial ZIPs, say Y.
+
+config BUSYBOX_CONFIG_FEATURE_UNZIP_BZIP2
+	bool "Support compression method 12 (bzip2)"
+	default BUSYBOX_DEFAULT_FEATURE_UNZIP_BZIP2
+	depends on BUSYBOX_CONFIG_FEATURE_UNZIP_CDF && BUSYBOX_CONFIG_DESKTOP
+
+config BUSYBOX_CONFIG_FEATURE_UNZIP_LZMA
+	bool "Support compression method 14 (lzma)"
+	default BUSYBOX_DEFAULT_FEATURE_UNZIP_LZMA
+	depends on BUSYBOX_CONFIG_FEATURE_UNZIP_CDF && BUSYBOX_CONFIG_DESKTOP
+
+config BUSYBOX_CONFIG_FEATURE_UNZIP_XZ
+	bool "Support compression method 95 (xz)"
+	default BUSYBOX_DEFAULT_FEATURE_UNZIP_XZ
+	depends on BUSYBOX_CONFIG_FEATURE_UNZIP_CDF && BUSYBOX_CONFIG_DESKTOP
+
+config BUSYBOX_CONFIG_FEATURE_LZMA_FAST
+	bool "Optimize lzma for speed"
+	default BUSYBOX_DEFAULT_FEATURE_LZMA_FAST
+	depends on BUSYBOX_CONFIG_UNLZMA || BUSYBOX_CONFIG_LZCAT || BUSYBOX_CONFIG_LZMA || BUSYBOX_CONFIG_FEATURE_SEAMLESS_LZMA
+	help
+	This option reduces decompression time by about 25% at the cost of
+	a 1K bigger binary.
+
+endmenu
diff --git a/package/utils/busybox/config/console-tools/Config.in b/package/utils/busybox/config/console-tools/Config.in
new file mode 100644
index 0000000..cf224e5
--- /dev/null
+++ b/package/utils/busybox/config/console-tools/Config.in
@@ -0,0 +1,144 @@
+# DO NOT EDIT. This file is generated from Config.src
+#
+# For a description of the syntax of this configuration file,
+# see docs/Kconfig-language.txt.
+#
+
+menu "Console Utilities"
+
+config BUSYBOX_CONFIG_CHVT
+	bool "chvt (2 kb)"
+	default BUSYBOX_DEFAULT_CHVT
+	help
+	This program is used to change to another terminal.
+	Example: chvt 4 (change to terminal /dev/tty4)
+config BUSYBOX_CONFIG_CLEAR
+	bool "clear (tiny)"
+	default BUSYBOX_DEFAULT_CLEAR
+	help
+	This program clears the terminal screen.
+config BUSYBOX_CONFIG_DEALLOCVT
+	bool "deallocvt (1.9 kb)"
+	default BUSYBOX_DEFAULT_DEALLOCVT
+	help
+	This program deallocates unused virtual consoles.
+config BUSYBOX_CONFIG_DUMPKMAP
+	bool "dumpkmap (1.6 kb)"
+	default BUSYBOX_DEFAULT_DUMPKMAP
+	help
+	This program dumps the kernel's keyboard translation table to
+	stdout, in binary format. You can then use loadkmap to load it.
+config BUSYBOX_CONFIG_FGCONSOLE
+	bool "fgconsole (1.5 kb)"
+	default BUSYBOX_DEFAULT_FGCONSOLE
+	help
+	This program prints active (foreground) console number.
+config BUSYBOX_CONFIG_KBD_MODE
+	bool "kbd_mode (4.1 kb)"
+	default BUSYBOX_DEFAULT_KBD_MODE
+	help
+	This program reports and sets keyboard mode.
+config BUSYBOX_CONFIG_LOADFONT
+	bool "loadfont (5.2 kb)"
+	default BUSYBOX_DEFAULT_LOADFONT
+	help
+	This program loads a console font from standard input.
+
+config BUSYBOX_CONFIG_SETFONT
+	bool "setfont (24 kb)"
+	default BUSYBOX_DEFAULT_SETFONT
+	help
+	Allows to load console screen map. Useful for i18n.
+
+config BUSYBOX_CONFIG_FEATURE_SETFONT_TEXTUAL_MAP
+	bool "Support reading textual screen maps"
+	default BUSYBOX_DEFAULT_FEATURE_SETFONT_TEXTUAL_MAP
+	depends on BUSYBOX_CONFIG_SETFONT
+	help
+	Support reading textual screen maps.
+
+config BUSYBOX_CONFIG_DEFAULT_SETFONT_DIR
+	string "Default directory for console-tools files"
+	default BUSYBOX_DEFAULT_DEFAULT_SETFONT_DIR
+	depends on BUSYBOX_CONFIG_SETFONT
+	help
+	Directory to use if setfont's params are simple filenames
+	(not /path/to/file or ./file). Default is "" (no default directory).
+
+comment "Common options for loadfont and setfont"
+	depends on BUSYBOX_CONFIG_LOADFONT || BUSYBOX_CONFIG_SETFONT
+
+config BUSYBOX_CONFIG_FEATURE_LOADFONT_PSF2
+	bool "Support PSF2 console fonts"
+	default BUSYBOX_DEFAULT_FEATURE_LOADFONT_PSF2
+	depends on BUSYBOX_CONFIG_LOADFONT || BUSYBOX_CONFIG_SETFONT
+
+config BUSYBOX_CONFIG_FEATURE_LOADFONT_RAW
+	bool "Support old (raw) console fonts"
+	default BUSYBOX_DEFAULT_FEATURE_LOADFONT_RAW
+	depends on BUSYBOX_CONFIG_LOADFONT || BUSYBOX_CONFIG_SETFONT
+config BUSYBOX_CONFIG_LOADKMAP
+	bool "loadkmap (1.8 kb)"
+	default BUSYBOX_DEFAULT_LOADKMAP
+	help
+	This program loads a keyboard translation table from
+	standard input.
+config BUSYBOX_CONFIG_OPENVT
+	bool "openvt (7.2 kb)"
+	default BUSYBOX_DEFAULT_OPENVT
+	help
+	This program is used to start a command on an unused
+	virtual terminal.
+config BUSYBOX_CONFIG_RESET
+	bool "reset (345 bytes)"
+	default BUSYBOX_DEFAULT_RESET
+	help
+	This program is used to reset the terminal screen, if it
+	gets messed up.
+config BUSYBOX_CONFIG_RESIZE
+	bool "resize (903 bytes)"
+	default BUSYBOX_DEFAULT_RESIZE
+	help
+	This program is used to (re)set the width and height of your current
+	terminal.
+
+config BUSYBOX_CONFIG_FEATURE_RESIZE_PRINT
+	bool "Print environment variables"
+	default BUSYBOX_DEFAULT_FEATURE_RESIZE_PRINT
+	depends on BUSYBOX_CONFIG_RESIZE
+	help
+	Prints the newly set size (number of columns and rows) of
+	the terminal.
+	E.g.:
+	COLUMNS=80;LINES=44;export COLUMNS LINES;
+config BUSYBOX_CONFIG_SETCONSOLE
+	bool "setconsole (3.6 kb)"
+	default BUSYBOX_DEFAULT_SETCONSOLE
+	help
+	Redirect writes to /dev/console to another device,
+	like the current tty while logged in via telnet.
+	This does not redirect kernel log, only writes
+	from user space.
+
+config BUSYBOX_CONFIG_FEATURE_SETCONSOLE_LONG_OPTIONS
+	bool "Enable long options"
+	default BUSYBOX_DEFAULT_FEATURE_SETCONSOLE_LONG_OPTIONS
+	depends on BUSYBOX_CONFIG_SETCONSOLE && BUSYBOX_CONFIG_LONG_OPTS
+config BUSYBOX_CONFIG_SETKEYCODES
+	bool "setkeycodes (2.1 kb)"
+	default BUSYBOX_DEFAULT_SETKEYCODES
+	help
+	This program loads entries into the kernel's scancode-to-keycode
+	map, allowing unusual keyboards to generate usable keycodes.
+config BUSYBOX_CONFIG_SETLOGCONS
+	bool "setlogcons (1.8 kb)"
+	default BUSYBOX_DEFAULT_SETLOGCONS
+	help
+	This program redirects the output console of kernel messages.
+config BUSYBOX_CONFIG_SHOWKEY
+	bool "showkey (4.7 kb)"
+	default BUSYBOX_DEFAULT_SHOWKEY
+	help
+	Shows keys pressed.
+
+endmenu
diff --git a/package/utils/busybox/config/coreutils/Config.in b/package/utils/busybox/config/coreutils/Config.in
new file mode 100644
index 0000000..983740b
--- /dev/null
+++ b/package/utils/busybox/config/coreutils/Config.in
@@ -0,0 +1,965 @@
+# DO NOT EDIT. This file is generated from Config.src
+#
+# For a description of the syntax of this configuration file,
+# see docs/Kconfig-language.txt.
+#
+
+menu "Coreutils"
+
+config BUSYBOX_CONFIG_FEATURE_VERBOSE
+	bool "Support verbose options (usually -v) for various applets"
+	default BUSYBOX_DEFAULT_FEATURE_VERBOSE
+	help
+	Enable cp -v, rm -v and similar messages.
+	Also enables long option (--verbose) if it exists.
+	Without this option, -v is accepted but ignored.
+
+comment "Common options for date and touch"
+
+config BUSYBOX_CONFIG_FEATURE_TIMEZONE
+	bool "Allow timezone in dates"
+	default BUSYBOX_DEFAULT_FEATURE_TIMEZONE
+	depends on BUSYBOX_CONFIG_DESKTOP
+	help
+	Permit the use of timezones when parsing user-provided data
+	strings, e.g. '1996-04-09 12:45:00 -0500'.
+
+	This requires support for the '%z' extension to strptime() which
+	may not be available in all implementations.
+
+comment "Common options for cp and mv"
+	depends on BUSYBOX_CONFIG_CP || BUSYBOX_CONFIG_MV
+
+config BUSYBOX_CONFIG_FEATURE_PRESERVE_HARDLINKS
+	bool "Preserve hard links"
+	default BUSYBOX_DEFAULT_FEATURE_PRESERVE_HARDLINKS
+	depends on BUSYBOX_CONFIG_CP || BUSYBOX_CONFIG_MV
+	help
+	Allow cp and mv to preserve hard links.
+
+comment "Common options for df, du, ls"
+	depends on BUSYBOX_CONFIG_DF || BUSYBOX_CONFIG_DU || BUSYBOX_CONFIG_LS
+
+config BUSYBOX_CONFIG_FEATURE_HUMAN_READABLE
+	bool "Support human readable output (example 13k, 23M, 235G)"
+	default BUSYBOX_DEFAULT_FEATURE_HUMAN_READABLE
+	depends on BUSYBOX_CONFIG_DF || BUSYBOX_CONFIG_DU || BUSYBOX_CONFIG_LS
+	help
+	Allow df, du, and ls to have human readable output.
+
+config BUSYBOX_CONFIG_BASENAME
+	bool "basename (438 bytes)"
+	default BUSYBOX_DEFAULT_BASENAME
+	help
+	basename is used to strip the directory and suffix from filenames,
+	leaving just the filename itself. Enable this option if you wish
+	to enable the 'basename' utility.
+config BUSYBOX_CONFIG_CAT
+	bool "cat (5.6 kb)"
+	default BUSYBOX_DEFAULT_CAT
+	help
+	cat is used to concatenate files and print them to the standard
+	output. Enable this option if you wish to enable the 'cat' utility.
+
+config BUSYBOX_CONFIG_FEATURE_CATN
+	bool "Enable -n and -b options"
+	default BUSYBOX_DEFAULT_FEATURE_CATN
+	depends on BUSYBOX_CONFIG_CAT
+	help
+	-n numbers all output lines while -b numbers nonempty output lines.
+
+config BUSYBOX_CONFIG_FEATURE_CATV
+	bool "cat -v[etA]"
+	default BUSYBOX_DEFAULT_FEATURE_CATV
+	depends on BUSYBOX_CONFIG_CAT
+	help
+	Display nonprinting characters as escape sequences
+config BUSYBOX_CONFIG_CHGRP
+	bool "chgrp (7.6 kb)"
+	default BUSYBOX_DEFAULT_CHGRP
+	help
+	chgrp is used to change the group ownership of files.
+config BUSYBOX_CONFIG_CHMOD
+	bool "chmod (5.5 kb)"
+	default BUSYBOX_DEFAULT_CHMOD
+	help
+	chmod is used to change the access permission of files.
+config BUSYBOX_CONFIG_CHOWN
+	bool "chown (7.6 kb)"
+	default BUSYBOX_DEFAULT_CHOWN
+	help
+	chown is used to change the user and/or group ownership
+	of files.
+
+config BUSYBOX_CONFIG_FEATURE_CHOWN_LONG_OPTIONS
+	bool "Enable long options"
+	default BUSYBOX_DEFAULT_FEATURE_CHOWN_LONG_OPTIONS
+	depends on BUSYBOX_CONFIG_CHOWN && BUSYBOX_CONFIG_LONG_OPTS
+config BUSYBOX_CONFIG_CHROOT
+	bool "chroot (3.7 kb)"
+	default BUSYBOX_DEFAULT_CHROOT
+	help
+	chroot is used to change the root directory and run a command.
+	The default command is '/bin/sh'.
+config BUSYBOX_CONFIG_CKSUM
+	bool "cksum (4.1 kb)"
+	default BUSYBOX_DEFAULT_CKSUM
+
+config BUSYBOX_CONFIG_CRC32
+	bool "crc32 (4.1 kb)"
+	default BUSYBOX_DEFAULT_CRC32
+config BUSYBOX_CONFIG_COMM
+	bool "comm (4.2 kb)"
+	default BUSYBOX_DEFAULT_COMM
+	help
+	comm is used to compare two files line by line and return
+	a three-column output.
+config BUSYBOX_CONFIG_CP
+	bool "cp (10 kb)"
+	default BUSYBOX_DEFAULT_CP
+	help
+	cp is used to copy files and directories.
+
+config BUSYBOX_CONFIG_FEATURE_CP_LONG_OPTIONS
+	bool "Enable long options"
+	default BUSYBOX_DEFAULT_FEATURE_CP_LONG_OPTIONS
+	depends on BUSYBOX_CONFIG_CP && BUSYBOX_CONFIG_LONG_OPTS
+	help
+	Enable long options.
+	Also add support for --parents option.
+
+config BUSYBOX_CONFIG_FEATURE_CP_REFLINK
+	bool "Enable --reflink[=auto]"
+	default BUSYBOX_DEFAULT_FEATURE_CP_REFLINK
+	depends on BUSYBOX_CONFIG_FEATURE_CP_LONG_OPTIONS
+config BUSYBOX_CONFIG_CUT
+	bool "cut (5.8 kb)"
+	default BUSYBOX_DEFAULT_CUT
+	help
+	cut is used to print selected parts of lines from
+	each file to stdout.
+
+config BUSYBOX_CONFIG_FEATURE_CUT_REGEX
+	bool "cut -F"
+	default BUSYBOX_DEFAULT_FEATURE_CUT_REGEX
+	depends on BUSYBOX_CONFIG_CUT
+	help
+	Allow regex based delimiters.
+config BUSYBOX_CONFIG_DATE
+	bool "date (7 kb)"
+	default BUSYBOX_DEFAULT_DATE
+	help
+	date is used to set the system date or display the
+	current time in the given format.
+
+config BUSYBOX_CONFIG_FEATURE_DATE_ISOFMT
+	bool "Enable ISO date format output (-I)"
+	default BUSYBOX_DEFAULT_FEATURE_DATE_ISOFMT
+	depends on BUSYBOX_CONFIG_DATE
+	help
+	Enable option (-I) to output an ISO-8601 compliant
+	date/time string.
+
+config BUSYBOX_CONFIG_FEATURE_DATE_NANO
+	bool "Support %[num]N nanosecond format specifier"
+	default BUSYBOX_DEFAULT_FEATURE_DATE_NANO # stat's nanosecond field is a bit non-portable
+	depends on BUSYBOX_CONFIG_DATE
+	help
+	Support %[num]N format specifier. Adds ~250 bytes of code.
+
+config BUSYBOX_CONFIG_FEATURE_DATE_COMPAT
+	bool "Support weird 'date MMDDhhmm[[YY]YY][.ss]' format"
+	default BUSYBOX_DEFAULT_FEATURE_DATE_COMPAT
+	depends on BUSYBOX_CONFIG_DATE
+	help
+	System time can be set by 'date -s DATE' and simply 'date DATE',
+	but formats of DATE string are different. 'date DATE' accepts
+	a rather weird MMDDhhmm[[YY]YY][.ss] format with completely
+	unnatural placement of year between minutes and seconds.
+	date -s (and other commands like touch -d) use more sensible
+	formats (for one, ISO format YYYY-MM-DD hh:mm:ss.ssssss).
+
+	With this option off, 'date DATE' and 'date -s DATE' support
+	the same format. With it on, 'date DATE' additionally supports
+	MMDDhhmm[[YY]YY][.ss] format.
+config BUSYBOX_CONFIG_DD
+	bool "dd (7.5 kb)"
+	default BUSYBOX_DEFAULT_DD
+	help
+	dd copies a file (from standard input to standard output,
+	by default) using specific input and output blocksizes,
+	while optionally performing conversions on it.
+
+config BUSYBOX_CONFIG_FEATURE_DD_SIGNAL_HANDLING
+	bool "Enable signal handling for status reporting"
+	default BUSYBOX_DEFAULT_FEATURE_DD_SIGNAL_HANDLING
+	depends on BUSYBOX_CONFIG_DD
+	help
+	Sending a SIGUSR1 signal to a running 'dd' process makes it
+	print to standard error the number of records read and written
+	so far, then to resume copying.
+
+	$ dd if=/dev/zero of=/dev/null &
+	$ pid=$!; kill -USR1 $pid; sleep 1; kill $pid
+	10899206+0 records in
+	10899206+0 records out
+
+config BUSYBOX_CONFIG_FEATURE_DD_THIRD_STATUS_LINE
+	bool "Enable the third status line upon signal"
+	default BUSYBOX_DEFAULT_FEATURE_DD_THIRD_STATUS_LINE
+	depends on BUSYBOX_CONFIG_DD && BUSYBOX_CONFIG_FEATURE_DD_SIGNAL_HANDLING
+	help
+	Displays a coreutils-like third status line with transferred bytes,
+	elapsed time and speed.
+
+config BUSYBOX_CONFIG_FEATURE_DD_IBS_OBS
+	bool "Enable ibs, obs, iflag, oflag and conv options"
+	default BUSYBOX_DEFAULT_FEATURE_DD_IBS_OBS
+	depends on BUSYBOX_CONFIG_DD
+	help
+	Enable support for writing a certain number of bytes in and out,
+	at a time, and performing conversions on the data stream.
+
+config BUSYBOX_CONFIG_FEATURE_DD_STATUS
+	bool "Enable status display options"
+	default BUSYBOX_DEFAULT_FEATURE_DD_STATUS
+	depends on BUSYBOX_CONFIG_DD
+	help
+	Enable support for status=noxfer/none option.
+config BUSYBOX_CONFIG_DF
+	bool "df (6.8 kb)"
+	default BUSYBOX_DEFAULT_DF
+	help
+	df reports the amount of disk space used and available
+	on filesystems.
+
+config BUSYBOX_CONFIG_FEATURE_DF_FANCY
+	bool "Enable -a, -i, -B"
+	default BUSYBOX_DEFAULT_FEATURE_DF_FANCY
+	depends on BUSYBOX_CONFIG_DF
+	help
+	-a Show all filesystems
+	-i Inodes
+	-B <SIZE> Blocksize
+
+config BUSYBOX_CONFIG_FEATURE_SKIP_ROOTFS
+	bool "Skip rootfs in mount table"
+	default BUSYBOX_DEFAULT_FEATURE_SKIP_ROOTFS
+	depends on BUSYBOX_CONFIG_DF
+	help
+	Ignore rootfs entry in mount table.
+
+	In Linux, kernel has a special filesystem, rootfs, which is initially
+	mounted on /. It contains initramfs data, if kernel is configured
+	to have one. Usually, another file system is mounted over / early
+	in boot process, and therefore most tools which manipulate
+	mount table, such as df, will skip rootfs entry.
+
+	However, some systems do not mount anything on /.
+	If you need to configure busybox for one of these systems,
+	you may find it useful to turn this option off to make df show
+	initramfs statistics.
+
+	Otherwise, choose Y.
+config BUSYBOX_CONFIG_DIRNAME
+	bool "dirname (329 bytes)"
+	default BUSYBOX_DEFAULT_DIRNAME
+	help
+	dirname is used to strip a non-directory suffix from
+	a file name.
+config BUSYBOX_CONFIG_DOS2UNIX
+	bool "dos2unix (5.2 kb)"
+	default BUSYBOX_DEFAULT_DOS2UNIX
+	help
+	dos2unix is used to convert a text file from DOS format to
+	UNIX format, and vice versa.
+
+config BUSYBOX_CONFIG_UNIX2DOS
+	bool "unix2dos (5.2 kb)"
+	default BUSYBOX_DEFAULT_UNIX2DOS
+	help
+	unix2dos is used to convert a text file from UNIX format to
+	DOS format, and vice versa.
+config BUSYBOX_CONFIG_DU
+	bool "du (6.3 kb)"
+	default BUSYBOX_DEFAULT_DU
+	help
+	du is used to report the amount of disk space used
+	for specified files.
+
+config BUSYBOX_CONFIG_FEATURE_DU_DEFAULT_BLOCKSIZE_1K
+	bool "Use default blocksize of 1024 bytes (else it's 512 bytes)"
+	default BUSYBOX_DEFAULT_FEATURE_DU_DEFAULT_BLOCKSIZE_1K
+	depends on BUSYBOX_CONFIG_DU
+config BUSYBOX_CONFIG_ECHO
+	bool "echo (1.8 kb)"
+	default BUSYBOX_DEFAULT_ECHO
+	help
+	echo prints a specified string to stdout.
+
+# this entry also appears in shell/Config.in, next to the echo builtin
+config BUSYBOX_CONFIG_FEATURE_FANCY_ECHO
+	bool "Enable -n and -e options"
+	default BUSYBOX_DEFAULT_FEATURE_FANCY_ECHO
+	depends on BUSYBOX_CONFIG_ECHO || BUSYBOX_CONFIG_ASH_ECHO || BUSYBOX_CONFIG_HUSH_ECHO
+config BUSYBOX_CONFIG_ENV
+	bool "env (4 kb)"
+	default BUSYBOX_DEFAULT_ENV
+	help
+	env is used to set an environment variable and run
+	a command; without options it displays the current
+	environment.
+config BUSYBOX_CONFIG_EXPAND
+	bool "expand (5.1 kb)"
+	default BUSYBOX_DEFAULT_EXPAND
+	help
+	By default, convert all tabs to spaces.
+
+config BUSYBOX_CONFIG_UNEXPAND
+	bool "unexpand (5.3 kb)"
+	default BUSYBOX_DEFAULT_UNEXPAND
+	help
+	By default, convert only leading sequences of blanks to tabs.
+config BUSYBOX_CONFIG_EXPR
+	bool "expr (6.6 kb)"
+	default BUSYBOX_DEFAULT_EXPR
+	help
+	expr is used to calculate numbers and print the result
+	to standard output.
+
+config BUSYBOX_CONFIG_EXPR_MATH_SUPPORT_64
+	bool "Extend Posix numbers support to 64 bit"
+	default BUSYBOX_DEFAULT_EXPR_MATH_SUPPORT_64
+	depends on BUSYBOX_CONFIG_EXPR
+	help
+	Enable 64-bit math support in the expr applet. This will make
+	the applet slightly larger, but will allow computation with very
+	large numbers.
+config BUSYBOX_CONFIG_FACTOR
+	bool "factor (2.7 kb)"
+	default BUSYBOX_DEFAULT_FACTOR
+	help
+	factor factorizes integers
+config BUSYBOX_CONFIG_FALSE
+	bool "false (tiny)"
+	default BUSYBOX_DEFAULT_FALSE
+	help
+	false returns an exit code of FALSE (1).
+config BUSYBOX_CONFIG_FOLD
+	bool "fold (4.6 kb)"
+	default BUSYBOX_DEFAULT_FOLD
+	help
+	Wrap text to fit a specific width.
+config BUSYBOX_CONFIG_HEAD
+	bool "head (3.8 kb)"
+	default BUSYBOX_DEFAULT_HEAD
+	help
+	head is used to print the first specified number of lines
+	from files.
+
+config BUSYBOX_CONFIG_FEATURE_FANCY_HEAD
+	bool "Enable -c, -q, and -v"
+	default BUSYBOX_DEFAULT_FEATURE_FANCY_HEAD
+	depends on BUSYBOX_CONFIG_HEAD
+config BUSYBOX_CONFIG_HOSTID
+	bool "hostid (286 bytes)"
+	default BUSYBOX_DEFAULT_HOSTID
+	help
+	hostid prints the numeric identifier (in hexadecimal) for
+	the current host.
+config BUSYBOX_CONFIG_ID
+	bool "id (7 kb)"
+	default BUSYBOX_DEFAULT_ID
+	help
+	id displays the current user and group ID names.
+
+config BUSYBOX_CONFIG_GROUPS
+	bool "groups (6.7 kb)"
+	default BUSYBOX_DEFAULT_GROUPS
+	help
+	Print the group names associated with current user id.
+config BUSYBOX_CONFIG_INSTALL
+	bool "install (12 kb)"
+	default BUSYBOX_DEFAULT_INSTALL
+	help
+	Copy files and set attributes.
+
+config BUSYBOX_CONFIG_FEATURE_INSTALL_LONG_OPTIONS
+	bool "Enable long options"
+	default BUSYBOX_DEFAULT_FEATURE_INSTALL_LONG_OPTIONS
+	depends on BUSYBOX_CONFIG_INSTALL && BUSYBOX_CONFIG_LONG_OPTS
+config BUSYBOX_CONFIG_LINK
+	bool "link (3.2 kb)"
+	default BUSYBOX_DEFAULT_LINK
+	help
+	link creates hard links between files.
+config BUSYBOX_CONFIG_LN
+	bool "ln (4.9 kb)"
+	default BUSYBOX_DEFAULT_LN
+	help
+	ln is used to create hard or soft links between files.
+config BUSYBOX_CONFIG_LOGNAME
+	bool "logname (1.1 kb)"
+	default BUSYBOX_DEFAULT_LOGNAME
+	help
+	logname is used to print the current user's login name.
+config BUSYBOX_CONFIG_LS
+	bool "ls (14 kb)"
+	default BUSYBOX_DEFAULT_LS
+	help
+	ls is used to list the contents of directories.
+
+config BUSYBOX_CONFIG_FEATURE_LS_FILETYPES
+	bool "Enable filetyping options (-p and -F)"
+	default BUSYBOX_DEFAULT_FEATURE_LS_FILETYPES
+	depends on BUSYBOX_CONFIG_LS
+
+config BUSYBOX_CONFIG_FEATURE_LS_FOLLOWLINKS
+	bool "Enable symlinks dereferencing (-L)"
+	default BUSYBOX_DEFAULT_FEATURE_LS_FOLLOWLINKS
+	depends on BUSYBOX_CONFIG_LS
+
+config BUSYBOX_CONFIG_FEATURE_LS_RECURSIVE
+	bool "Enable recursion (-R)"
+	default BUSYBOX_DEFAULT_FEATURE_LS_RECURSIVE
+	depends on BUSYBOX_CONFIG_LS
+
+config BUSYBOX_CONFIG_FEATURE_LS_WIDTH
+	bool "Enable -w WIDTH and window size autodetection"
+	default BUSYBOX_DEFAULT_FEATURE_LS_WIDTH
+	depends on BUSYBOX_CONFIG_LS
+
+config BUSYBOX_CONFIG_FEATURE_LS_SORTFILES
+	bool "Sort the file names"
+	default BUSYBOX_DEFAULT_FEATURE_LS_SORTFILES
+	depends on BUSYBOX_CONFIG_LS
+	help
+	Allow ls to sort file names alphabetically.
+
+config BUSYBOX_CONFIG_FEATURE_LS_TIMESTAMPS
+	bool "Show file timestamps"
+	default BUSYBOX_DEFAULT_FEATURE_LS_TIMESTAMPS
+	depends on BUSYBOX_CONFIG_LS
+	help
+	Allow ls to display timestamps for files.
+
+config BUSYBOX_CONFIG_FEATURE_LS_USERNAME
+	bool "Show username/groupnames"
+	default BUSYBOX_DEFAULT_FEATURE_LS_USERNAME
+	depends on BUSYBOX_CONFIG_LS
+	help
+	Allow ls to display username/groupname for files.
+
+config BUSYBOX_CONFIG_FEATURE_LS_COLOR
+	bool "Allow use of color to identify file types"
+	default BUSYBOX_DEFAULT_FEATURE_LS_COLOR
+	depends on BUSYBOX_CONFIG_LS && BUSYBOX_CONFIG_LONG_OPTS
+	help
+	This enables the --color option to ls.
+
+config BUSYBOX_CONFIG_FEATURE_LS_COLOR_IS_DEFAULT
+	bool "Produce colored ls output by default"
+	default BUSYBOX_DEFAULT_FEATURE_LS_COLOR_IS_DEFAULT
+	depends on BUSYBOX_CONFIG_FEATURE_LS_COLOR
+	help
+	Saying yes here will turn coloring on by default,
+	even if no "--color" option is given to the ls command.
+	This is not recommended, since the colors are not
+	configurable, and the output may not be legible on
+	many output screens.
+config BUSYBOX_CONFIG_MD5SUM
+	bool "md5sum (6.5 kb)"
+	default BUSYBOX_DEFAULT_MD5SUM
+	help
+	Compute and check MD5 message digest
+
+config BUSYBOX_CONFIG_SHA1SUM
+	bool "sha1sum (5.9 kb)"
+	default BUSYBOX_DEFAULT_SHA1SUM
+	help
+	Compute and check SHA1 message digest
+
+config BUSYBOX_CONFIG_SHA256SUM
+	bool "sha256sum (7 kb)"
+	default BUSYBOX_DEFAULT_SHA256SUM
+	help
+	Compute and check SHA256 message digest
+
+config BUSYBOX_CONFIG_SHA512SUM
+	bool "sha512sum (7.4 kb)"
+	default BUSYBOX_DEFAULT_SHA512SUM
+	help
+	Compute and check SHA512 message digest
+
+config BUSYBOX_CONFIG_SHA3SUM
+	bool "sha3sum (6.1 kb)"
+	default BUSYBOX_DEFAULT_SHA3SUM
+	help
+	Compute and check SHA3 message digest
+
+comment "Common options for md5sum, sha1sum, sha256sum, sha512sum, sha3sum"
+	depends on BUSYBOX_CONFIG_MD5SUM || BUSYBOX_CONFIG_SHA1SUM || BUSYBOX_CONFIG_SHA256SUM || BUSYBOX_CONFIG_SHA512SUM || BUSYBOX_CONFIG_SHA3SUM
+
+config BUSYBOX_CONFIG_FEATURE_MD5_SHA1_SUM_CHECK
+	bool "Enable -c, -s and -w options"
+	default BUSYBOX_DEFAULT_FEATURE_MD5_SHA1_SUM_CHECK
+	depends on BUSYBOX_CONFIG_MD5SUM || BUSYBOX_CONFIG_SHA1SUM || BUSYBOX_CONFIG_SHA256SUM || BUSYBOX_CONFIG_SHA512SUM || BUSYBOX_CONFIG_SHA3SUM
+	help
+	Enabling the -c options allows files to be checked
+	against pre-calculated hash values.
+	-s and -w are useful options when verifying checksums.
+config BUSYBOX_CONFIG_MKDIR
+	bool "mkdir (4.5 kb)"
+	default BUSYBOX_DEFAULT_MKDIR
+	help
+	mkdir is used to create directories with the specified names.
+config BUSYBOX_CONFIG_MKFIFO
+	bool "mkfifo (3.8 kb)"
+	default BUSYBOX_DEFAULT_MKFIFO
+	help
+	mkfifo is used to create FIFOs (named pipes).
+	The 'mknod' program can also create FIFOs.
+config BUSYBOX_CONFIG_MKNOD
+	bool "mknod (4.5 kb)"
+	default BUSYBOX_DEFAULT_MKNOD
+	help
+	mknod is used to create FIFOs or block/character special
+	files with the specified names.
+config BUSYBOX_CONFIG_MKTEMP
+	bool "mktemp (4.2 kb)"
+	default BUSYBOX_DEFAULT_MKTEMP
+	help
+	mktemp is used to create unique temporary files
+config BUSYBOX_CONFIG_MV
+	bool "mv (10 kb)"
+	default BUSYBOX_DEFAULT_MV
+	help
+	mv is used to move or rename files or directories.
+config BUSYBOX_CONFIG_NICE
+	bool "nice (2.1 kb)"
+	default BUSYBOX_DEFAULT_NICE
+	help
+	nice runs a program with modified scheduling priority.
+config BUSYBOX_CONFIG_NL
+	bool "nl (4.6 kb)"
+	default BUSYBOX_DEFAULT_NL
+	help
+	nl is used to number lines of files.
+config BUSYBOX_CONFIG_NOHUP
+	bool "nohup (2 kb)"
+	default BUSYBOX_DEFAULT_NOHUP
+	help
+	run a command immune to hangups, with output to a non-tty.
+config BUSYBOX_CONFIG_NPROC
+	bool "nproc (3.7 kb)"
+	default BUSYBOX_DEFAULT_NPROC
+	help
+	Print number of CPUs
+config BUSYBOX_CONFIG_OD
+	bool "od (11 kb)"
+	default BUSYBOX_DEFAULT_OD
+	help
+	od is used to dump binary files in octal and other formats.
+config BUSYBOX_CONFIG_PASTE
+	bool "paste (4.9 kb)"
+	default BUSYBOX_DEFAULT_PASTE
+	help
+	paste is used to paste lines of different files together
+	and write the result to stdout
+config BUSYBOX_CONFIG_PRINTENV
+	bool "printenv (1.3 kb)"
+	default BUSYBOX_DEFAULT_PRINTENV
+	help
+	printenv is used to print all or part of environment.
+config BUSYBOX_CONFIG_PRINTF
+	bool "printf (3.8 kb)"
+	default BUSYBOX_DEFAULT_PRINTF
+	help
+	printf is used to format and print specified strings.
+	It's similar to 'echo' except it has more options.
+config BUSYBOX_CONFIG_PWD
+	bool "pwd (3.7 kb)"
+	default BUSYBOX_DEFAULT_PWD
+	help
+	pwd is used to print the current directory.
+config BUSYBOX_CONFIG_READLINK
+	bool "readlink (4 kb)"
+	default BUSYBOX_DEFAULT_READLINK
+	help
+	This program reads a symbolic link and returns the name
+	of the file it points to
+
+config BUSYBOX_CONFIG_FEATURE_READLINK_FOLLOW
+	bool "Enable canonicalization by following all symlinks (-f)"
+	default BUSYBOX_DEFAULT_FEATURE_READLINK_FOLLOW
+	depends on BUSYBOX_CONFIG_READLINK
+	help
+	Enable the readlink option (-f).
+config BUSYBOX_CONFIG_REALPATH
+	bool "realpath (1.6 kb)"
+	default BUSYBOX_DEFAULT_REALPATH
+	help
+	Return the canonicalized absolute pathname.
+	This isn't provided by GNU shellutils, but where else does it belong.
+config BUSYBOX_CONFIG_RM
+	bool "rm (5.4 kb)"
+	default BUSYBOX_DEFAULT_RM
+	help
+	rm is used to remove files or directories.
+config BUSYBOX_CONFIG_RMDIR
+	bool "rmdir (3.5 kb)"
+	default BUSYBOX_DEFAULT_RMDIR
+	help
+	rmdir is used to remove empty directories.
+config BUSYBOX_CONFIG_SEQ
+	bool "seq (3.8 kb)"
+	default BUSYBOX_DEFAULT_SEQ
+	help
+	print a sequence of numbers
+config BUSYBOX_CONFIG_SHRED
+	bool "shred (4.9 kb)"
+	default BUSYBOX_DEFAULT_SHRED
+	help
+	Overwrite a file to hide its contents, and optionally delete it
+config BUSYBOX_CONFIG_SHUF
+	bool "shuf (5.4 kb)"
+	default BUSYBOX_DEFAULT_SHUF
+	help
+	Generate random permutations
+config BUSYBOX_CONFIG_SLEEP
+	bool "sleep (2 kb)"
+	default BUSYBOX_DEFAULT_SLEEP
+	help
+	sleep is used to pause for a specified number of seconds.
+	It comes in 3 versions:
+	- small: takes one integer parameter
+	- fancy: takes multiple integer arguments with suffixes:
+		sleep 1d 2h 3m 15s
+	- fancy with fractional numbers:
+		sleep 2.3s 4.5h sleeps for 16202.3 seconds
+	Last one is "the most compatible" with coreutils sleep,
+	but it adds around 1k of code.
+
+config BUSYBOX_CONFIG_FEATURE_FANCY_SLEEP
+	bool "Enable multiple arguments and s/m/h/d suffixes"
+	default BUSYBOX_DEFAULT_FEATURE_FANCY_SLEEP
+	depends on BUSYBOX_CONFIG_SLEEP
+	help
+	Allow sleep to pause for specified minutes, hours, and days.
+config BUSYBOX_CONFIG_SORT
+	bool "sort (7.7 kb)"
+	default BUSYBOX_DEFAULT_SORT
+	help
+	sort is used to sort lines of text in specified files.
+
+config BUSYBOX_CONFIG_FEATURE_SORT_BIG
+	bool "Full SuSv3 compliant sort (support -ktcbdfioghM)"
+	default BUSYBOX_DEFAULT_FEATURE_SORT_BIG
+	depends on BUSYBOX_CONFIG_SORT
+	help
+	Without this, sort only supports -rusz, and an integer version
+	of -n. Selecting this adds sort keys, floating point support, and
+	more. This adds a little over 3k to a nonstatic build on x86.
+
+	The SuSv3 sort standard is available at:
+	http://www.opengroup.org/onlinepubs/007904975/utilities/sort.html
+
+config BUSYBOX_CONFIG_FEATURE_SORT_OPTIMIZE_MEMORY
+	bool "Use less memory (but might be slower)"
+	default BUSYBOX_DEFAULT_FEATURE_SORT_OPTIMIZE_MEMORY   # defaults to N since we are size-paranoid tribe
+	depends on BUSYBOX_CONFIG_SORT
+	help
+	Attempt to use less memory (by storing only one copy
+	of duplicated lines, and such). Useful if you work on huge files.
+config BUSYBOX_CONFIG_SPLIT
+	bool "split (5 kb)"
+	default BUSYBOX_DEFAULT_SPLIT
+	help
+	Split a file into pieces.
+
+config BUSYBOX_CONFIG_FEATURE_SPLIT_FANCY
+	bool "Fancy extensions"
+	default BUSYBOX_DEFAULT_FEATURE_SPLIT_FANCY
+	depends on BUSYBOX_CONFIG_SPLIT
+	help
+	Add support for features not required by SUSv3.
+	Supports additional suffixes 'b' for 512 bytes,
+	'g' for 1GiB for the -b option.
+config BUSYBOX_CONFIG_STAT
+	bool "stat (11 kb)"
+	default BUSYBOX_DEFAULT_STAT
+	help
+	display file or filesystem status.
+
+config BUSYBOX_CONFIG_FEATURE_STAT_FORMAT
+	bool "Enable custom formats (-c)"
+	default BUSYBOX_DEFAULT_FEATURE_STAT_FORMAT
+	depends on BUSYBOX_CONFIG_STAT
+	help
+	Without this, stat will not support the '-c format' option where
+	users can pass a custom format string for output. This adds about
+	7k to a nonstatic build on amd64.
+
+config BUSYBOX_CONFIG_FEATURE_STAT_FILESYSTEM
+	bool "Enable display of filesystem status (-f)"
+	default BUSYBOX_DEFAULT_FEATURE_STAT_FILESYSTEM
+	depends on BUSYBOX_CONFIG_STAT
+	help
+	Without this, stat will not support the '-f' option to display
+	information about filesystem status.
+config BUSYBOX_CONFIG_STTY
+	bool "stty (8.9 kb)"
+	default BUSYBOX_DEFAULT_STTY
+	help
+	stty is used to change and print terminal line settings.
+config BUSYBOX_CONFIG_SUM
+	bool "sum (4 kb)"
+	default BUSYBOX_DEFAULT_SUM
+	help
+	checksum and count the blocks in a file
+config BUSYBOX_CONFIG_SYNC
+	bool "sync (3.8 kb)"
+	default BUSYBOX_DEFAULT_SYNC
+	help
+	sync is used to flush filesystem buffers.
+config BUSYBOX_CONFIG_FEATURE_SYNC_FANCY
+	bool "Enable -d and -f flags (requires syncfs(2) in libc)"
+	default BUSYBOX_DEFAULT_FEATURE_SYNC_FANCY
+	depends on BUSYBOX_CONFIG_SYNC
+	help
+	sync -d FILE... executes fdatasync() on each FILE.
+	sync -f FILE... executes syncfs() on each FILE.
+config BUSYBOX_CONFIG_FSYNC
+	bool "fsync (3.6 kb)"
+	default BUSYBOX_DEFAULT_FSYNC
+	help
+	fsync is used to flush file-related cached blocks to disk.
+config BUSYBOX_CONFIG_TAC
+	bool "tac (3.9 kb)"
+	default BUSYBOX_DEFAULT_TAC
+	help
+	tac is used to concatenate and print files in reverse.
+config BUSYBOX_CONFIG_TAIL
+	bool "tail (6.8 kb)"
+	default BUSYBOX_DEFAULT_TAIL
+	help
+	tail is used to print the last specified number of lines
+	from files.
+
+config BUSYBOX_CONFIG_FEATURE_FANCY_TAIL
+	bool "Enable -q, -s, -v, and -F options"
+	default BUSYBOX_DEFAULT_FEATURE_FANCY_TAIL
+	depends on BUSYBOX_CONFIG_TAIL
+	help
+	These options are provided by GNU tail, but
+	are not specified in the SUSv3 standard:
+		-q      Never output headers giving file names
+		-s SEC  Wait SEC seconds between reads with -f
+		-v      Always output headers giving file names
+		-F      Same as -f, but keep retrying
+config BUSYBOX_CONFIG_TEE
+	bool "tee (4.2 kb)"
+	default BUSYBOX_DEFAULT_TEE
+	help
+	tee is used to read from standard input and write
+	to standard output and files.
+
+config BUSYBOX_CONFIG_FEATURE_TEE_USE_BLOCK_IO
+	bool "Enable block I/O (larger/faster) instead of byte I/O"
+	default BUSYBOX_DEFAULT_FEATURE_TEE_USE_BLOCK_IO
+	depends on BUSYBOX_CONFIG_TEE
+	help
+	Enable this option for a faster tee, at expense of size.
+config BUSYBOX_CONFIG_TEST
+	bool "test (4.1 kb)"
+	default BUSYBOX_DEFAULT_TEST
+	help
+	test is used to check file types and compare values,
+	returning an appropriate exit code. The bash shell
+	has test built in, ash can build it in optionally.
+
+config BUSYBOX_CONFIG_TEST1
+	bool "test as ["
+	default BUSYBOX_DEFAULT_TEST1
+	help
+	Provide test command in the "[ EXPR ]" form
+
+config BUSYBOX_CONFIG_TEST2
+	bool "test as [["
+	default BUSYBOX_DEFAULT_TEST2
+	help
+	Provide test command in the "[[ EXPR ]]" form
+
+config BUSYBOX_CONFIG_FEATURE_TEST_64
+	bool "Extend test to 64 bit"
+	default BUSYBOX_DEFAULT_FEATURE_TEST_64
+	depends on BUSYBOX_CONFIG_TEST || BUSYBOX_CONFIG_TEST1 || BUSYBOX_CONFIG_TEST2 || BUSYBOX_CONFIG_ASH_TEST || BUSYBOX_CONFIG_HUSH_TEST
+	help
+	Enable 64-bit support in test.
+config BUSYBOX_CONFIG_TIMEOUT
+	bool "timeout (6 kb)"
+	default BUSYBOX_DEFAULT_TIMEOUT
+	help
+	Runs a program and watches it. If it does not terminate in
+	specified number of seconds, it is sent a signal.
+config BUSYBOX_CONFIG_TOUCH
+	bool "touch (5.9 kb)"
+	default BUSYBOX_DEFAULT_TOUCH
+	help
+	touch is used to create or change the access and/or
+	modification timestamp of specified files.
+
+config BUSYBOX_CONFIG_FEATURE_TOUCH_SUSV3
+	bool "Add support for SUSV3 features (-a -d -m -t -r)"
+	default BUSYBOX_DEFAULT_FEATURE_TOUCH_SUSV3
+	depends on BUSYBOX_CONFIG_TOUCH
+	help
+	Enable touch to use a reference file or a given date/time argument.
+config BUSYBOX_CONFIG_TR
+	bool "tr (5.1 kb)"
+	default BUSYBOX_DEFAULT_TR
+	help
+	tr is used to squeeze, and/or delete characters from standard
+	input, writing to standard output.
+
+config BUSYBOX_CONFIG_FEATURE_TR_CLASSES
+	bool "Enable character classes (such as [:upper:])"
+	default BUSYBOX_DEFAULT_FEATURE_TR_CLASSES
+	depends on BUSYBOX_CONFIG_TR
+	help
+	Enable character classes, enabling commands such as:
+	tr [:upper:] [:lower:] to convert input into lowercase.
+
+config BUSYBOX_CONFIG_FEATURE_TR_EQUIV
+	bool "Enable equivalence classes"
+	default BUSYBOX_DEFAULT_FEATURE_TR_EQUIV
+	depends on BUSYBOX_CONFIG_TR
+	help
+	Enable equivalence classes, which essentially add the enclosed
+	character to the current set. For instance, tr [=a=] xyz would
+	replace all instances of 'a' with 'xyz'. This option is mainly
+	useful for cases when no other way of expressing a character
+	is possible.
+config BUSYBOX_CONFIG_TRUE
+	bool "true (tiny)"
+	default BUSYBOX_DEFAULT_TRUE
+	help
+	true returns an exit code of TRUE (0).
+config BUSYBOX_CONFIG_TRUNCATE
+	bool "truncate (4.2 kb)"
+	default BUSYBOX_DEFAULT_TRUNCATE
+	help
+	truncate truncates files to a given size. If a file does
+	not exist, it is created unless told otherwise.
+config BUSYBOX_CONFIG_TSORT
+	bool "tsort (0.7 kb)"
+	default BUSYBOX_DEFAULT_TSORT
+	help
+	tsort performs a topological sort.
+config BUSYBOX_CONFIG_TTY
+	bool "tty (3.6 kb)"
+	default BUSYBOX_DEFAULT_TTY
+	help
+	tty is used to print the name of the current terminal to
+	standard output.
+config BUSYBOX_CONFIG_UNAME
+	bool "uname (3.9 kb)"
+	default BUSYBOX_DEFAULT_UNAME
+	help
+	uname is used to print system information.
+
+config BUSYBOX_CONFIG_UNAME_OSNAME
+	string "Operating system name"
+	default BUSYBOX_DEFAULT_UNAME_OSNAME
+	depends on BUSYBOX_CONFIG_UNAME
+	help
+	Sets the operating system name reported by uname -o.  The
+	default BUSYBOX_DEFAULT_UNAME_OSNAME "GNU/Linux".
+
+config BUSYBOX_CONFIG_BB_ARCH
+	bool "arch (1.1 kb)"
+	default BUSYBOX_DEFAULT_BB_ARCH
+	help
+	Same as uname -m.
+config BUSYBOX_CONFIG_UNIQ
+	bool "uniq (4.9 kb)"
+	default BUSYBOX_DEFAULT_UNIQ
+	help
+	uniq is used to remove duplicate lines from a sorted file.
+config BUSYBOX_CONFIG_UNLINK
+	bool "unlink (3.2 kb)"
+	default BUSYBOX_DEFAULT_UNLINK
+	help
+	unlink deletes a file by calling unlink()
+config BUSYBOX_CONFIG_USLEEP
+	bool "usleep (1.3 kb)"
+	default BUSYBOX_DEFAULT_USLEEP
+	help
+	usleep is used to pause for a specified number of microseconds.
+config BUSYBOX_CONFIG_UUDECODE
+	bool "uudecode (5.8 kb)"
+	default BUSYBOX_DEFAULT_UUDECODE
+	help
+	uudecode is used to decode a uuencoded file.
+config BUSYBOX_CONFIG_BASE32
+	bool "base32 (4.9 kb)"
+	default BUSYBOX_DEFAULT_BASE32
+	help
+	Base32 encode and decode
+config BUSYBOX_CONFIG_BASE64
+	bool "base64 (4.9 kb)"
+	default BUSYBOX_DEFAULT_BASE64
+	help
+	Base64 encode and decode
+config BUSYBOX_CONFIG_UUENCODE
+	bool "uuencode (4.4 kb)"
+	default BUSYBOX_DEFAULT_UUENCODE
+	help
+	uuencode is used to uuencode a file.
+config BUSYBOX_CONFIG_WC
+	bool "wc (4.5 kb)"
+	default BUSYBOX_DEFAULT_WC
+	help
+	wc is used to print the number of bytes, words, and lines,
+	in specified files.
+
+config BUSYBOX_CONFIG_FEATURE_WC_LARGE
+	bool "Support very large counts"
+	default BUSYBOX_DEFAULT_FEATURE_WC_LARGE
+	depends on BUSYBOX_CONFIG_WC
+	help
+	Use "unsigned long long" for counter variables.
+config BUSYBOX_CONFIG_WHO
+	bool "who (3.9 kb)"
+	default BUSYBOX_DEFAULT_WHO
+	depends on BUSYBOX_CONFIG_FEATURE_UTMP
+	help
+	Print users currently logged on.
+
+config BUSYBOX_CONFIG_W
+	bool "w (3.8 kb)"
+	default BUSYBOX_DEFAULT_W
+	depends on BUSYBOX_CONFIG_FEATURE_UTMP
+	help
+	Print users currently logged on.
+
+config BUSYBOX_CONFIG_USERS
+	bool "users (3.4 kb)"
+	default BUSYBOX_DEFAULT_USERS
+	depends on BUSYBOX_CONFIG_FEATURE_UTMP
+	help
+	Print users currently logged on.
+config BUSYBOX_CONFIG_WHOAMI
+	bool "whoami (3.2 kb)"
+	default BUSYBOX_DEFAULT_WHOAMI
+	help
+	whoami is used to print the username of the current
+	user id (same as id -un).
+config BUSYBOX_CONFIG_YES
+	bool "yes (1.2 kb)"
+	default BUSYBOX_DEFAULT_YES
+	help
+	yes is used to repeatedly output a specific string, or
+	the default string 'y'.
+
+endmenu
diff --git a/package/utils/busybox/config/debianutils/Config.in b/package/utils/busybox/config/debianutils/Config.in
new file mode 100644
index 0000000..15abb08
--- /dev/null
+++ b/package/utils/busybox/config/debianutils/Config.in
@@ -0,0 +1,70 @@
+# DO NOT EDIT. This file is generated from Config.src
+#
+# For a description of the syntax of this configuration file,
+# see docs/Kconfig-language.txt.
+#
+
+menu "Debian Utilities"
+
+config BUSYBOX_CONFIG_PIPE_PROGRESS
+	bool "pipe_progress (275 bytes)"
+	default BUSYBOX_DEFAULT_PIPE_PROGRESS
+	help
+	Display a dot to indicate pipe activity.
+config BUSYBOX_CONFIG_RUN_PARTS
+	bool "run-parts (6.1 kb)"
+	default BUSYBOX_DEFAULT_RUN_PARTS
+	help
+	run-parts is a utility designed to run all the scripts in a directory.
+
+	It is useful to set up a directory like cron.daily, where you need to
+	execute all the scripts in that directory.
+
+	In this implementation of run-parts some features (such as report
+	mode) are not implemented.
+
+	Unless you know that run-parts is used in some of your scripts
+	you can safely say N here.
+
+config BUSYBOX_CONFIG_FEATURE_RUN_PARTS_LONG_OPTIONS
+	bool "Enable long options"
+	default BUSYBOX_DEFAULT_FEATURE_RUN_PARTS_LONG_OPTIONS
+	depends on BUSYBOX_CONFIG_RUN_PARTS && BUSYBOX_CONFIG_LONG_OPTS
+
+config BUSYBOX_CONFIG_FEATURE_RUN_PARTS_FANCY
+	bool "Support additional arguments"
+	default BUSYBOX_DEFAULT_FEATURE_RUN_PARTS_FANCY
+	depends on BUSYBOX_CONFIG_RUN_PARTS
+	help
+	Support additional options:
+	-l --list print the names of the all matching files (not
+	limited to executables), but don't actually run them.
+config BUSYBOX_CONFIG_START_STOP_DAEMON
+	bool "start-stop-daemon (12 kb)"
+	default BUSYBOX_DEFAULT_START_STOP_DAEMON
+	help
+	start-stop-daemon is used to control the creation and
+	termination of system-level processes, usually the ones
+	started during the startup of the system.
+
+config BUSYBOX_CONFIG_FEATURE_START_STOP_DAEMON_LONG_OPTIONS
+	bool "Enable long options"
+	default BUSYBOX_DEFAULT_FEATURE_START_STOP_DAEMON_LONG_OPTIONS
+	depends on BUSYBOX_CONFIG_START_STOP_DAEMON && BUSYBOX_CONFIG_LONG_OPTS
+
+config BUSYBOX_CONFIG_FEATURE_START_STOP_DAEMON_FANCY
+	bool "Support additional arguments"
+	default BUSYBOX_DEFAULT_FEATURE_START_STOP_DAEMON_FANCY
+	depends on BUSYBOX_CONFIG_START_STOP_DAEMON
+	help
+	-o|--oknodo ignored since we exit with 0 anyway
+	-v|--verbose
+	-N|--nicelevel N
+config BUSYBOX_CONFIG_WHICH
+	bool "which (3.8 kb)"
+	default BUSYBOX_DEFAULT_WHICH
+	help
+	which is used to find programs in your PATH and
+	print out their pathnames.
+
+endmenu
diff --git a/package/utils/busybox/config/e2fsprogs/Config.in b/package/utils/busybox/config/e2fsprogs/Config.in
new file mode 100644
index 0000000..4a9aa2a
--- /dev/null
+++ b/package/utils/busybox/config/e2fsprogs/Config.in
@@ -0,0 +1,66 @@
+# DO NOT EDIT. This file is generated from Config.src
+#
+# For a description of the syntax of this configuration file,
+# see docs/Kconfig-language.txt.
+#
+
+menu "Linux Ext2 FS Progs"
+
+config BUSYBOX_CONFIG_CHATTR
+	bool "chattr (3.8 kb)"
+	default BUSYBOX_DEFAULT_CHATTR
+	help
+	chattr changes the file attributes on a second extended file system.
+config BUSYBOX_CONFIG_FSCK
+	bool "fsck (7.4 kb)"
+	default BUSYBOX_DEFAULT_FSCK
+	help
+	fsck is used to check and optionally repair one or more filesystems.
+	In actuality, fsck is simply a front-end for the various file system
+	checkers (fsck.fstype) available under Linux.
+config BUSYBOX_CONFIG_LSATTR
+	bool "lsattr (5.5 kb)"
+	default BUSYBOX_DEFAULT_LSATTR
+	help
+	lsattr lists the file attributes on a second extended file system.
+config BUSYBOX_CONFIG_TUNE2FS
+	bool "tune2fs (4.4 kb)"
+	default BUSYBOX_DEFAULT_TUNE2FS  # off: it is too limited compared to upstream version
+	help
+	tune2fs allows the system administrator to adjust various tunable
+	filesystem parameters on Linux ext2/ext3 filesystems.
+
+### config E2FSCK
+###	bool "e2fsck"
+###	default y
+###	help
+###	  e2fsck is used to check Linux second extended file systems (ext2fs).
+###	  e2fsck also supports ext2 filesystems countaining a journal (ext3).
+###	  The normal compat symlinks 'fsck.ext2' and 'fsck.ext3' are also
+###	  provided.
+
+### config MKE2FS
+###	bool "mke2fs"
+###	default y
+###	help
+###	  mke2fs is used to create an ext2/ext3 filesystem. The normal compat
+###	  symlinks 'mkfs.ext2' and 'mkfs.ext3' are also provided.
+
+### config E2LABEL
+###	bool "e2label"
+###	default y
+###	depends on TUNE2FS
+###	help
+###	  e2label will display or change the filesystem label on the ext2
+###	  filesystem located on device.
+
+### NB: this one is now provided by util-linux/volume_id/*
+### config FINDFS
+###	bool "findfs"
+###	default y
+###	depends on TUNE2FS
+###	help
+###	  findfs will search the disks in the system looking for a filesystem
+###	  which has a label matching label or a UUID equal to uuid.
+
+endmenu
diff --git a/package/utils/busybox/config/e2fsprogs/old_e2fsprogs/Config.in b/package/utils/busybox/config/e2fsprogs/old_e2fsprogs/Config.in
new file mode 100644
index 0000000..cfa6313
--- /dev/null
+++ b/package/utils/busybox/config/e2fsprogs/old_e2fsprogs/Config.in
@@ -0,0 +1,69 @@
+# DO NOT EDIT. This file is generated from Config.src
+#
+# For a description of the syntax of this configuration file,
+# see scripts/kbuild/config-language.txt.
+#
+
+menu "Linux Ext2 FS Progs"
+
+
+config BUSYBOX_CONFIG_CHATTR
+	bool "chattr"
+	default BUSYBOX_DEFAULT_CHATTR
+	help
+	chattr changes the file attributes on a second extended file system.
+
+config BUSYBOX_CONFIG_E2FSCK
+	bool "e2fsck"
+	default BUSYBOX_DEFAULT_E2FSCK
+	help
+	e2fsck is used to check Linux second extended file systems (ext2fs).
+	e2fsck also supports ext2 filesystems countaining a journal (ext3).
+	The normal compat symlinks 'fsck.ext2' and 'fsck.ext3' are also
+	provided.
+
+config BUSYBOX_CONFIG_FSCK
+	bool "fsck"
+	default BUSYBOX_DEFAULT_FSCK
+	help
+	fsck is used to check and optionally repair one or more filesystems.
+	In actuality, fsck is simply a front-end for the various file system
+	checkers (fsck.fstype) available under Linux.
+
+config BUSYBOX_CONFIG_LSATTR
+	bool "lsattr"
+	default BUSYBOX_DEFAULT_LSATTR
+	help
+	lsattr lists the file attributes on a second extended file system.
+
+config BUSYBOX_CONFIG_MKE2FS
+	bool "mke2fs"
+	default BUSYBOX_DEFAULT_MKE2FS
+	help
+	mke2fs is used to create an ext2/ext3 filesystem. The normal compat
+	symlinks 'mkfs.ext2' and 'mkfs.ext3' are also provided.
+
+config BUSYBOX_CONFIG_TUNE2FS
+	bool "tune2fs"
+	default BUSYBOX_DEFAULT_TUNE2FS
+	help
+	tune2fs allows the system administrator to adjust various tunable
+	filesystem parameters on Linux ext2/ext3 filesystems.
+
+config BUSYBOX_CONFIG_E2LABEL
+	bool "e2label"
+	default BUSYBOX_DEFAULT_E2LABEL
+	depends on BUSYBOX_CONFIG_TUNE2FS
+	help
+	e2label will display or change the filesystem label on the ext2
+	filesystem located on device.
+
+config BUSYBOX_CONFIG_FINDFS
+	bool "findfs"
+	default BUSYBOX_DEFAULT_FINDFS
+	depends on BUSYBOX_CONFIG_TUNE2FS
+	help
+	findfs will search the disks in the system looking for a filesystem
+	which has a label matching label or a UUID equal to uuid.
+
+endmenu
diff --git a/package/utils/busybox/config/editors/Config.in b/package/utils/busybox/config/editors/Config.in
new file mode 100644
index 0000000..dc80a4e
--- /dev/null
+++ b/package/utils/busybox/config/editors/Config.in
@@ -0,0 +1,245 @@
+# DO NOT EDIT. This file is generated from Config.src
+#
+# For a description of the syntax of this configuration file,
+# see docs/Kconfig-language.txt.
+#
+
+menu "Editors"
+
+config BUSYBOX_CONFIG_AWK
+	bool "awk (23 kb)"
+	default BUSYBOX_DEFAULT_AWK
+	help
+	Awk is used as a pattern scanning and processing language.
+
+config BUSYBOX_CONFIG_FEATURE_AWK_LIBM
+	bool "Enable math functions (requires libm)"
+	default BUSYBOX_DEFAULT_FEATURE_AWK_LIBM
+	depends on BUSYBOX_CONFIG_AWK
+	help
+	Enable math functions of the Awk programming language.
+	NOTE: This requires libm to be present for linking.
+
+config BUSYBOX_CONFIG_FEATURE_AWK_GNU_EXTENSIONS
+	bool "Enable a few GNU extensions"
+	default BUSYBOX_DEFAULT_FEATURE_AWK_GNU_EXTENSIONS
+	depends on BUSYBOX_CONFIG_AWK
+	help
+	Enable a few features from gawk:
+	* command line option -e AWK_PROGRAM
+	* simultaneous use of -f and -e on the command line.
+	This enables the use of awk library files.
+	Example: awk -f mylib.awk -e '{print myfunction($1);}' ...
+config BUSYBOX_CONFIG_CMP
+	bool "cmp (4.9 kb)"
+	default BUSYBOX_DEFAULT_CMP
+	help
+	cmp is used to compare two files and returns the result
+	to standard output.
+config BUSYBOX_CONFIG_DIFF
+	bool "diff (13 kb)"
+	default BUSYBOX_DEFAULT_DIFF
+	help
+	diff compares two files or directories and outputs the
+	differences between them in a form that can be given to
+	the patch command.
+
+config BUSYBOX_CONFIG_FEATURE_DIFF_LONG_OPTIONS
+	bool "Enable long options"
+	default BUSYBOX_DEFAULT_FEATURE_DIFF_LONG_OPTIONS
+	depends on BUSYBOX_CONFIG_DIFF && BUSYBOX_CONFIG_LONG_OPTS
+
+config BUSYBOX_CONFIG_FEATURE_DIFF_DIR
+	bool "Enable directory support"
+	default BUSYBOX_DEFAULT_FEATURE_DIFF_DIR
+	depends on BUSYBOX_CONFIG_DIFF
+	help
+	This option enables support for directory and subdirectory
+	comparison.
+config BUSYBOX_CONFIG_ED
+	bool "ed (21 kb)"
+	default BUSYBOX_DEFAULT_ED
+	help
+	The original 1970's Unix text editor, from the days of teletypes.
+	Small, simple, evil. Part of SUSv3. If you're not already using
+	this, you don't need it.
+config BUSYBOX_CONFIG_PATCH
+	bool "patch (9.4 kb)"
+	default BUSYBOX_DEFAULT_PATCH
+	help
+	Apply a unified diff formatted patch.
+config BUSYBOX_CONFIG_SED
+	bool "sed (12 kb)"
+	default BUSYBOX_DEFAULT_SED
+	help
+	sed is used to perform text transformations on a file
+	or input from a pipeline.
+config BUSYBOX_CONFIG_VI
+	bool "vi (23 kb)"
+	default BUSYBOX_DEFAULT_VI
+	help
+	'vi' is a text editor. More specifically, it is the One True
+	text editor <grin>. It does, however, have a rather steep
+	learning curve. If you are not already comfortable with 'vi'
+	you may wish to use something else.
+
+config BUSYBOX_CONFIG_FEATURE_VI_MAX_LEN
+	int "Maximum screen width"
+	range 256 16384
+	default BUSYBOX_DEFAULT_FEATURE_VI_MAX_LEN
+	depends on BUSYBOX_CONFIG_VI
+	help
+	Contrary to what you may think, this is not eating much.
+	Make it smaller than 4k only if you are very limited on memory.
+
+config BUSYBOX_CONFIG_FEATURE_VI_8BIT
+	bool "Allow to display 8-bit chars (otherwise shows dots)"
+	default BUSYBOX_DEFAULT_FEATURE_VI_8BIT
+	depends on BUSYBOX_CONFIG_VI
+	help
+	If your terminal can display characters with high bit set,
+	you may want to enable this. Note: vi is not Unicode-capable.
+	If your terminal combines several 8-bit bytes into one character
+	(as in Unicode mode), this will not work properly.
+
+config BUSYBOX_CONFIG_FEATURE_VI_COLON
+	bool "Enable \":\" colon commands (no \"ex\" mode)"
+	default BUSYBOX_DEFAULT_FEATURE_VI_COLON
+	depends on BUSYBOX_CONFIG_VI
+	help
+	Enable a limited set of colon commands. This does not
+	provide an "ex" mode.
+
+config BUSYBOX_CONFIG_FEATURE_VI_COLON_EXPAND
+	bool "Expand \"%\" and \"#\" in colon commands"
+	default BUSYBOX_DEFAULT_FEATURE_VI_COLON_EXPAND
+	depends on BUSYBOX_CONFIG_FEATURE_VI_COLON
+	help
+	Expand the special characters \"%\" (current filename)
+	and \"#\" (alternate filename) in colon commands.
+
+config BUSYBOX_CONFIG_FEATURE_VI_YANKMARK
+	bool "Enable yank/put commands and mark cmds"
+	default BUSYBOX_DEFAULT_FEATURE_VI_YANKMARK
+	depends on BUSYBOX_CONFIG_VI
+	help
+	This enables you to use yank and put, as well as mark.
+
+config BUSYBOX_CONFIG_FEATURE_VI_SEARCH
+	bool "Enable search and replace cmds"
+	default BUSYBOX_DEFAULT_FEATURE_VI_SEARCH
+	depends on BUSYBOX_CONFIG_VI
+	help
+	Select this if you wish to be able to do search and replace.
+
+config BUSYBOX_CONFIG_FEATURE_VI_REGEX_SEARCH
+	bool "Enable regex in search and replace"
+	default BUSYBOX_DEFAULT_FEATURE_VI_REGEX_SEARCH   # Uses GNU regex, which may be unavailable. FIXME
+	depends on BUSYBOX_CONFIG_FEATURE_VI_SEARCH
+	depends on USE_GLIBC
+	help
+	Use extended regex search.
+
+config BUSYBOX_CONFIG_FEATURE_VI_USE_SIGNALS
+	bool "Catch signals"
+	default BUSYBOX_DEFAULT_FEATURE_VI_USE_SIGNALS
+	depends on BUSYBOX_CONFIG_VI
+	help
+	Selecting this option will make vi signal aware. This will support
+	SIGWINCH to deal with Window Changes, catch ^Z and ^C and alarms.
+
+config BUSYBOX_CONFIG_FEATURE_VI_DOT_CMD
+	bool "Remember previous cmd and \".\" cmd"
+	default BUSYBOX_DEFAULT_FEATURE_VI_DOT_CMD
+	depends on BUSYBOX_CONFIG_VI
+	help
+	Make vi remember the last command and be able to repeat it.
+
+config BUSYBOX_CONFIG_FEATURE_VI_READONLY
+	bool "Enable -R option and \"view\" mode"
+	default BUSYBOX_DEFAULT_FEATURE_VI_READONLY
+	depends on BUSYBOX_CONFIG_VI
+	help
+	Enable the read-only command line option, which allows the user to
+	open a file in read-only mode.
+
+config BUSYBOX_CONFIG_FEATURE_VI_SETOPTS
+	bool "Enable settable options, ai ic showmatch"
+	default BUSYBOX_DEFAULT_FEATURE_VI_SETOPTS
+	depends on BUSYBOX_CONFIG_VI
+	help
+	Enable the editor to set some (ai, ic, showmatch) options.
+
+config BUSYBOX_CONFIG_FEATURE_VI_SET
+	bool "Support :set"
+	default BUSYBOX_DEFAULT_FEATURE_VI_SET
+	depends on BUSYBOX_CONFIG_VI
+
+config BUSYBOX_CONFIG_FEATURE_VI_WIN_RESIZE
+	bool "Handle window resize"
+	default BUSYBOX_DEFAULT_FEATURE_VI_WIN_RESIZE
+	depends on BUSYBOX_CONFIG_VI
+	help
+	Behave nicely with terminals that get resized.
+
+config BUSYBOX_CONFIG_FEATURE_VI_ASK_TERMINAL
+	bool "Use 'tell me cursor position' ESC sequence to measure window"
+	default BUSYBOX_DEFAULT_FEATURE_VI_ASK_TERMINAL
+	depends on BUSYBOX_CONFIG_VI
+	help
+	If terminal size can't be retrieved and $LINES/$COLUMNS are not set,
+	this option makes vi perform a last-ditch effort to find it:
+	position cursor to 999,999 and ask terminal to report real
+	cursor position using "ESC [ 6 n" escape sequence, then read stdin.
+	This is not clean but helps a lot on serial lines and such.
+
+config BUSYBOX_CONFIG_FEATURE_VI_UNDO
+	bool "Support undo command \"u\""
+	default BUSYBOX_DEFAULT_FEATURE_VI_UNDO
+	depends on BUSYBOX_CONFIG_VI
+	help
+	Support the 'u' command to undo insertion, deletion, and replacement
+	of text.
+
+config BUSYBOX_CONFIG_FEATURE_VI_UNDO_QUEUE
+	bool "Enable undo operation queuing"
+	default BUSYBOX_DEFAULT_FEATURE_VI_UNDO_QUEUE
+	depends on BUSYBOX_CONFIG_FEATURE_VI_UNDO
+	help
+	The vi undo functions can use an intermediate queue to greatly lower
+	malloc() calls and overhead. When the maximum size of this queue is
+	reached, the contents of the queue are committed to the undo stack.
+	This increases the size of the undo code and allows some undo
+	operations (especially un-typing/backspacing) to be far more useful.
+
+config BUSYBOX_CONFIG_FEATURE_VI_UNDO_QUEUE_MAX
+	int "Maximum undo character queue size"
+	default BUSYBOX_DEFAULT_FEATURE_VI_UNDO_QUEUE_MAX
+	range 32 65536
+	depends on BUSYBOX_CONFIG_FEATURE_VI_UNDO_QUEUE
+	help
+	This option sets the number of bytes used at runtime for the queue.
+	Smaller values will create more undo objects and reduce the amount
+	of typed or backspaced characters that are grouped into one undo
+	operation; larger values increase the potential size of each undo
+	and will generally malloc() larger objects and less frequently.
+	Unless you want more (or less) frequent "undo points" while typing,
+	you should probably leave this unchanged.
+
+config BUSYBOX_CONFIG_FEATURE_VI_VERBOSE_STATUS
+	bool "Enable verbose status reporting"
+	default BUSYBOX_DEFAULT_FEATURE_VI_VERBOSE_STATUS
+	depends on BUSYBOX_CONFIG_VI
+	help
+	Enable more verbose reporting of the results of yank, change,
+	delete, undo and substitution commands.
+
+config BUSYBOX_CONFIG_FEATURE_ALLOW_EXEC
+	bool "Allow vi and awk to execute shell commands"
+	default BUSYBOX_DEFAULT_FEATURE_ALLOW_EXEC
+	depends on BUSYBOX_CONFIG_VI || BUSYBOX_CONFIG_AWK
+	help
+	Enables vi and awk features which allow user to execute
+	shell commands (using system() C call).
+
+endmenu
diff --git a/package/utils/busybox/config/findutils/Config.in b/package/utils/busybox/config/findutils/Config.in
new file mode 100644
index 0000000..805d44f
--- /dev/null
+++ b/package/utils/busybox/config/findutils/Config.in
@@ -0,0 +1,318 @@
+# DO NOT EDIT. This file is generated from Config.src
+#
+# For a description of the syntax of this configuration file,
+# see docs/Kconfig-language.txt.
+#
+
+menu "Finding Utilities"
+
+config BUSYBOX_CONFIG_FIND
+	bool "find (14 kb)"
+	default BUSYBOX_DEFAULT_FIND
+	help
+	find is used to search your system to find specified files.
+
+config BUSYBOX_CONFIG_FEATURE_FIND_PRINT0
+	bool "Enable -print0: NUL-terminated output"
+	default BUSYBOX_DEFAULT_FEATURE_FIND_PRINT0
+	depends on BUSYBOX_CONFIG_FIND
+	help
+	Causes output names to be separated by a NUL character
+	rather than a newline. This allows names that contain
+	newlines and other whitespace to be more easily
+	interpreted by other programs.
+
+config BUSYBOX_CONFIG_FEATURE_FIND_MTIME
+	bool "Enable -mtime: modification time matching"
+	default BUSYBOX_DEFAULT_FEATURE_FIND_MTIME
+	depends on BUSYBOX_CONFIG_FIND
+	help
+	Allow searching based on the modification time of
+	files, in days.
+
+config BUSYBOX_CONFIG_FEATURE_FIND_ATIME
+	bool "Enable -atime: access time matching"
+	default BUSYBOX_DEFAULT_FEATURE_FIND_ATIME
+	depends on BUSYBOX_CONFIG_FEATURE_FIND_MTIME
+	help
+	Allow searching based on the access time of
+	files, in days.
+
+config BUSYBOX_CONFIG_FEATURE_FIND_CTIME
+	bool "Enable -ctime: status change timestamp matching"
+	default BUSYBOX_DEFAULT_FEATURE_FIND_CTIME
+	depends on BUSYBOX_CONFIG_FEATURE_FIND_MTIME
+	help
+	Allow searching based on the status change timestamp of
+	files, in days.
+
+config BUSYBOX_CONFIG_FEATURE_FIND_MMIN
+	bool "Enable -mmin: modification time matching by minutes"
+	default BUSYBOX_DEFAULT_FEATURE_FIND_MMIN
+	depends on BUSYBOX_CONFIG_FIND
+	help
+	Allow searching based on the modification time of
+	files, in minutes.
+
+config BUSYBOX_CONFIG_FEATURE_FIND_AMIN
+	bool "Enable -amin: access time matching by minutes"
+	default BUSYBOX_DEFAULT_FEATURE_FIND_AMIN
+	depends on BUSYBOX_CONFIG_FEATURE_FIND_MMIN
+	help
+	Allow searching based on the access time of
+	files, in minutes.
+
+config BUSYBOX_CONFIG_FEATURE_FIND_CMIN
+	bool "Enable -cmin: status change timestamp matching by minutes"
+	default BUSYBOX_DEFAULT_FEATURE_FIND_CMIN
+	depends on BUSYBOX_CONFIG_FEATURE_FIND_MMIN
+	help
+	Allow searching based on the status change timestamp of
+	files, in minutes.
+
+config BUSYBOX_CONFIG_FEATURE_FIND_PERM
+	bool "Enable -perm: permissions matching"
+	default BUSYBOX_DEFAULT_FEATURE_FIND_PERM
+	depends on BUSYBOX_CONFIG_FIND
+
+config BUSYBOX_CONFIG_FEATURE_FIND_TYPE
+	bool "Enable -type: file type matching (file/dir/link/...)"
+	default BUSYBOX_DEFAULT_FEATURE_FIND_TYPE
+	depends on BUSYBOX_CONFIG_FIND
+	help
+	Enable searching based on file type (file,
+	directory, socket, device, etc.).
+
+config BUSYBOX_CONFIG_FEATURE_FIND_EXECUTABLE
+	bool "Enable -executable: file is executable"
+	default BUSYBOX_DEFAULT_FEATURE_FIND_EXECUTABLE
+	depends on BUSYBOX_CONFIG_FIND
+
+config BUSYBOX_CONFIG_FEATURE_FIND_XDEV
+	bool "Enable -xdev: 'stay in filesystem'"
+	default BUSYBOX_DEFAULT_FEATURE_FIND_XDEV
+	depends on BUSYBOX_CONFIG_FIND
+
+config BUSYBOX_CONFIG_FEATURE_FIND_MAXDEPTH
+	bool "Enable -mindepth N and -maxdepth N"
+	default BUSYBOX_DEFAULT_FEATURE_FIND_MAXDEPTH
+	depends on BUSYBOX_CONFIG_FIND
+
+config BUSYBOX_CONFIG_FEATURE_FIND_NEWER
+	bool "Enable -newer: compare file modification times"
+	default BUSYBOX_DEFAULT_FEATURE_FIND_NEWER
+	depends on BUSYBOX_CONFIG_FIND
+	help
+	Support the 'find -newer' option for finding any files which have
+	modification time that is more recent than the specified FILE.
+
+config BUSYBOX_CONFIG_FEATURE_FIND_INUM
+	bool "Enable -inum: inode number matching"
+	default BUSYBOX_DEFAULT_FEATURE_FIND_INUM
+	depends on BUSYBOX_CONFIG_FIND
+
+config BUSYBOX_CONFIG_FEATURE_FIND_SAMEFILE
+	bool "Enable -samefile: reference file matching"
+	default BUSYBOX_DEFAULT_FEATURE_FIND_SAMEFILE
+	depends on BUSYBOX_CONFIG_FIND
+	help
+	Support the 'find -samefile' option for searching by a reference file.
+
+config BUSYBOX_CONFIG_FEATURE_FIND_EXEC
+	bool "Enable -exec: execute commands"
+	default BUSYBOX_DEFAULT_FEATURE_FIND_EXEC
+	depends on BUSYBOX_CONFIG_FIND
+	help
+	Support the 'find -exec' option for executing commands based upon
+	the files matched.
+
+config BUSYBOX_CONFIG_FEATURE_FIND_EXEC_PLUS
+	bool "Enable -exec ... {} +"
+	default BUSYBOX_DEFAULT_FEATURE_FIND_EXEC_PLUS
+	depends on BUSYBOX_CONFIG_FEATURE_FIND_EXEC
+	help
+	Support the 'find -exec ... {} +' option for executing commands
+	for all matched files at once.
+	Without this option, -exec + is a synonym for -exec ;
+	(IOW: it works correctly, but without expected speedup)
+
+config BUSYBOX_CONFIG_FEATURE_FIND_USER
+	bool "Enable -user: username/uid matching"
+	default BUSYBOX_DEFAULT_FEATURE_FIND_USER
+	depends on BUSYBOX_CONFIG_FIND
+
+config BUSYBOX_CONFIG_FEATURE_FIND_GROUP
+	bool "Enable -group: group/gid matching"
+	default BUSYBOX_DEFAULT_FEATURE_FIND_GROUP
+	depends on BUSYBOX_CONFIG_FIND
+
+config BUSYBOX_CONFIG_FEATURE_FIND_NOT
+	bool "Enable the 'not' (!) operator"
+	default BUSYBOX_DEFAULT_FEATURE_FIND_NOT
+	depends on BUSYBOX_CONFIG_FIND
+	help
+	Support the '!' operator to invert the test results.
+	If 'Enable full-blown desktop' is enabled, then will also support
+	the non-POSIX notation '-not'.
+
+config BUSYBOX_CONFIG_FEATURE_FIND_DEPTH
+	bool "Enable -depth"
+	default BUSYBOX_DEFAULT_FEATURE_FIND_DEPTH
+	depends on BUSYBOX_CONFIG_FIND
+	help
+	Process each directory's contents before the directory itself.
+
+config BUSYBOX_CONFIG_FEATURE_FIND_PAREN
+	bool "Enable parens in options"
+	default BUSYBOX_DEFAULT_FEATURE_FIND_PAREN
+	depends on BUSYBOX_CONFIG_FIND
+	help
+	Enable usage of parens '(' to specify logical order of arguments.
+
+config BUSYBOX_CONFIG_FEATURE_FIND_SIZE
+	bool "Enable -size: file size matching"
+	default BUSYBOX_DEFAULT_FEATURE_FIND_SIZE
+	depends on BUSYBOX_CONFIG_FIND
+
+config BUSYBOX_CONFIG_FEATURE_FIND_PRUNE
+	bool "Enable -prune: exclude subdirectories"
+	default BUSYBOX_DEFAULT_FEATURE_FIND_PRUNE
+	depends on BUSYBOX_CONFIG_FIND
+	help
+	If the file is a directory, don't descend into it. Useful for
+	exclusion .svn and CVS directories.
+
+config BUSYBOX_CONFIG_FEATURE_FIND_QUIT
+	bool "Enable -quit: exit"
+	default BUSYBOX_DEFAULT_FEATURE_FIND_QUIT
+	depends on BUSYBOX_CONFIG_FIND
+	help
+	If this action is reached, 'find' exits.
+
+config BUSYBOX_CONFIG_FEATURE_FIND_DELETE
+	bool "Enable -delete: delete files/dirs"
+	default BUSYBOX_DEFAULT_FEATURE_FIND_DELETE
+	depends on BUSYBOX_CONFIG_FIND && BUSYBOX_CONFIG_FEATURE_FIND_DEPTH
+	help
+	Support the 'find -delete' option for deleting files and directories.
+	WARNING: This option can do much harm if used wrong. Busybox will not
+	try to protect the user from doing stupid things. Use with care.
+
+config BUSYBOX_CONFIG_FEATURE_FIND_EMPTY
+	bool "Enable -empty: match empty files or directories"
+	default BUSYBOX_DEFAULT_FEATURE_FIND_EMPTY
+	depends on BUSYBOX_CONFIG_FIND
+	help
+	Support the 'find -empty' option to find empty regular files
+	or directories.
+
+config BUSYBOX_CONFIG_FEATURE_FIND_PATH
+	bool "Enable -path: match pathname with shell pattern"
+	default BUSYBOX_DEFAULT_FEATURE_FIND_PATH
+	depends on BUSYBOX_CONFIG_FIND
+	help
+	The -path option matches whole pathname instead of just filename.
+
+config BUSYBOX_CONFIG_FEATURE_FIND_REGEX
+	bool "Enable -regex: match pathname with regex"
+	default BUSYBOX_DEFAULT_FEATURE_FIND_REGEX
+	depends on BUSYBOX_CONFIG_FIND
+	help
+	The -regex option matches whole pathname against regular expression.
+
+config BUSYBOX_CONFIG_FEATURE_FIND_CONTEXT
+	bool "Enable -context: security context matching"
+	default BUSYBOX_DEFAULT_FEATURE_FIND_CONTEXT
+	depends on BUSYBOX_CONFIG_FIND && BUSYBOX_CONFIG_SELINUX
+	help
+	Support the 'find -context' option for matching security context.
+
+config BUSYBOX_CONFIG_FEATURE_FIND_LINKS
+	bool "Enable -links: link count matching"
+	default BUSYBOX_DEFAULT_FEATURE_FIND_LINKS
+	depends on BUSYBOX_CONFIG_FIND
+	help
+	Support the 'find -links' option for matching number of links.
+config BUSYBOX_CONFIG_GREP
+	bool "grep (8.6 kb)"
+	default BUSYBOX_DEFAULT_GREP
+	help
+	grep is used to search files for a specified pattern.
+
+config BUSYBOX_CONFIG_EGREP
+	bool "egrep (7.8 kb)"
+	default BUSYBOX_DEFAULT_EGREP
+	help
+	Alias to "grep -E".
+
+config BUSYBOX_CONFIG_FGREP
+	bool "fgrep (7.8 kb)"
+	default BUSYBOX_DEFAULT_FGREP
+	help
+	Alias to "grep -F".
+
+config BUSYBOX_CONFIG_FEATURE_GREP_CONTEXT
+	bool "Enable before and after context flags (-A, -B and -C)"
+	default BUSYBOX_DEFAULT_FEATURE_GREP_CONTEXT
+	depends on BUSYBOX_CONFIG_GREP || BUSYBOX_CONFIG_EGREP || BUSYBOX_CONFIG_FGREP
+	help
+	Print the specified number of leading (-B) and/or trailing (-A)
+	context surrounding our matching lines.
+	Print the specified number of context lines (-C).
+config BUSYBOX_CONFIG_XARGS
+	bool "xargs (7.2 kb)"
+	default BUSYBOX_DEFAULT_XARGS
+	help
+	xargs is used to execute a specified command for
+	every item from standard input.
+
+config BUSYBOX_CONFIG_FEATURE_XARGS_SUPPORT_CONFIRMATION
+	bool "Enable -p: prompt and confirmation"
+	default BUSYBOX_DEFAULT_FEATURE_XARGS_SUPPORT_CONFIRMATION
+	depends on BUSYBOX_CONFIG_XARGS
+	help
+	Support -p: prompt the user whether to run each command
+	line and read a line from the terminal.
+
+config BUSYBOX_CONFIG_FEATURE_XARGS_SUPPORT_QUOTES
+	bool "Enable single and double quotes and backslash"
+	default BUSYBOX_DEFAULT_FEATURE_XARGS_SUPPORT_QUOTES
+	depends on BUSYBOX_CONFIG_XARGS
+	help
+	Support quoting in the input.
+
+config BUSYBOX_CONFIG_FEATURE_XARGS_SUPPORT_TERMOPT
+	bool "Enable -x: exit if -s or -n is exceeded"
+	default BUSYBOX_DEFAULT_FEATURE_XARGS_SUPPORT_TERMOPT
+	depends on BUSYBOX_CONFIG_XARGS
+	help
+	Support -x: exit if the command size (see the -s or -n option)
+	is exceeded.
+
+config BUSYBOX_CONFIG_FEATURE_XARGS_SUPPORT_ZERO_TERM
+	bool "Enable -0: NUL-terminated input"
+	default BUSYBOX_DEFAULT_FEATURE_XARGS_SUPPORT_ZERO_TERM
+	depends on BUSYBOX_CONFIG_XARGS
+	help
+	Support -0: input items are terminated by a NUL character
+	instead of whitespace, and the quotes and backslash
+	are not special.
+
+config BUSYBOX_CONFIG_FEATURE_XARGS_SUPPORT_REPL_STR
+	bool "Enable -I STR: string to replace"
+	default BUSYBOX_DEFAULT_FEATURE_XARGS_SUPPORT_REPL_STR
+	depends on BUSYBOX_CONFIG_XARGS
+	help
+	Support -I STR and -i[STR] options.
+
+config BUSYBOX_CONFIG_FEATURE_XARGS_SUPPORT_PARALLEL
+	bool "Enable -P N: processes to run in parallel"
+	default BUSYBOX_DEFAULT_FEATURE_XARGS_SUPPORT_PARALLEL
+	depends on BUSYBOX_CONFIG_XARGS
+
+config BUSYBOX_CONFIG_FEATURE_XARGS_SUPPORT_ARGS_FILE
+	bool "Enable -a FILE: use FILE instead of stdin"
+	default BUSYBOX_DEFAULT_FEATURE_XARGS_SUPPORT_ARGS_FILE
+	depends on BUSYBOX_CONFIG_XARGS
+
+endmenu
diff --git a/package/utils/busybox/config/init/Config.in b/package/utils/busybox/config/init/Config.in
new file mode 100644
index 0000000..fc6c916
--- /dev/null
+++ b/package/utils/busybox/config/init/Config.in
@@ -0,0 +1,206 @@
+# DO NOT EDIT. This file is generated from Config.src
+#
+# For a description of the syntax of this configuration file,
+# see docs/Kconfig-language.txt.
+#
+
+menu "Init Utilities"
+
+config BUSYBOX_CONFIG_BOOTCHARTD
+	bool "bootchartd (10 kb)"
+	default BUSYBOX_DEFAULT_BOOTCHARTD
+	help
+	bootchartd is commonly used to profile the boot process
+	for the purpose of speeding it up. In this case, it is started
+	by the kernel as the init process. This is configured by adding
+	the init=/sbin/bootchartd option to the kernel command line.
+
+	It can also be used to monitor the resource usage of a specific
+	application or the running system in general. In this case,
+	bootchartd is started interactively by running bootchartd start
+	and stopped using bootchartd stop.
+
+config BUSYBOX_CONFIG_FEATURE_BOOTCHARTD_BLOATED_HEADER
+	bool "Compatible, bloated header"
+	default BUSYBOX_DEFAULT_FEATURE_BOOTCHARTD_BLOATED_HEADER
+	depends on BUSYBOX_CONFIG_BOOTCHARTD
+	help
+	Create extended header file compatible with "big" bootchartd.
+	"Big" bootchartd is a shell script and it dumps some
+	"convenient" info into the header, such as:
+		title = Boot chart for `hostname` (`date`)
+		system.uname = `uname -srvm`
+		system.release = `cat /etc/DISTRO-release`
+		system.cpu = `grep '^model name' /proc/cpuinfo | head -1` ($cpucount)
+		system.kernel.options = `cat /proc/cmdline`
+	This data is not mandatory for bootchart graph generation,
+	and is considered bloat. Nevertheless, this option
+	makes bootchartd applet to dump a subset of it.
+
+config BUSYBOX_CONFIG_FEATURE_BOOTCHARTD_CONFIG_FILE
+	bool "Support bootchartd.conf"
+	default BUSYBOX_DEFAULT_FEATURE_BOOTCHARTD_CONFIG_FILE
+	depends on BUSYBOX_CONFIG_BOOTCHARTD
+	help
+	Enable reading and parsing of $PWD/bootchartd.conf
+	and /etc/bootchartd.conf files.
+config BUSYBOX_CONFIG_HALT
+	bool "halt (4 kb)"
+	default BUSYBOX_DEFAULT_HALT
+	help
+	Stop all processes and halt the system.
+
+config BUSYBOX_CONFIG_POWEROFF
+	bool "poweroff (4 kb)"
+	default BUSYBOX_DEFAULT_POWEROFF
+	help
+	Stop all processes and power off the system.
+
+config BUSYBOX_CONFIG_REBOOT
+	bool "reboot (4 kb)"
+	default BUSYBOX_DEFAULT_REBOOT
+	help
+	Stop all processes and reboot the system.
+
+config BUSYBOX_CONFIG_FEATURE_WAIT_FOR_INIT
+	bool "Before signaling init, make sure it is ready for it"
+	default BUSYBOX_DEFAULT_FEATURE_WAIT_FOR_INIT
+	depends on BUSYBOX_CONFIG_HALT || BUSYBOX_CONFIG_POWEROFF || BUSYBOX_CONFIG_REBOOT
+	help
+	In rare cases, poweroff may be commanded by firmware to OS
+	even before init process exists. On Linux, this spawns
+	"/sbin/poweroff" very early. This option adds code
+	which checks that init is ready to receive poweroff
+	commands. Code size increase of ~80 bytes.
+
+config BUSYBOX_CONFIG_FEATURE_CALL_TELINIT
+	bool "Call telinit on shutdown and reboot"
+	default BUSYBOX_DEFAULT_FEATURE_CALL_TELINIT
+	depends on (BUSYBOX_CONFIG_HALT || BUSYBOX_CONFIG_POWEROFF || BUSYBOX_CONFIG_REBOOT) && !BUSYBOX_CONFIG_INIT
+	help
+	Call an external program (normally telinit) to facilitate
+	a switch to a proper runlevel.
+
+	This option is only available if you selected halt and friends,
+	but did not select init.
+
+config BUSYBOX_CONFIG_TELINIT_PATH
+	string "Path to telinit executable"
+	default BUSYBOX_DEFAULT_TELINIT_PATH
+	depends on BUSYBOX_CONFIG_FEATURE_CALL_TELINIT
+	help
+	When busybox halt and friends have to call external telinit
+	to facilitate proper shutdown, this path is to be used when
+	locating telinit executable.
+config BUSYBOX_CONFIG_INIT
+	bool "init (10 kb)"
+	default BUSYBOX_DEFAULT_INIT
+	select BUSYBOX_CONFIG_FEATURE_SYSLOG
+	help
+	init is the first program run when the system boots.
+
+config BUSYBOX_CONFIG_LINUXRC
+	bool "linuxrc: support running init from initrd (not initramfs)"
+	default BUSYBOX_DEFAULT_LINUXRC
+	select BUSYBOX_CONFIG_FEATURE_SYSLOG
+	help
+	Legacy support for running init under the old-style initrd. Allows
+	the name linuxrc to act as init, and it doesn't assume init is PID 1.
+
+	This does not apply to initramfs, which runs /init as PID 1 and
+	requires no special support.
+
+config BUSYBOX_CONFIG_FEATURE_USE_INITTAB
+	bool "Support reading an inittab file"
+	default BUSYBOX_DEFAULT_FEATURE_USE_INITTAB
+	depends on BUSYBOX_CONFIG_INIT || BUSYBOX_CONFIG_LINUXRC
+	help
+	Allow init to read an inittab file when the system boot.
+
+config BUSYBOX_CONFIG_FEATURE_KILL_REMOVED
+	bool "Support killing processes that have been removed from inittab"
+	default BUSYBOX_DEFAULT_FEATURE_KILL_REMOVED
+	depends on BUSYBOX_CONFIG_FEATURE_USE_INITTAB
+	help
+	When respawn entries are removed from inittab and a SIGHUP is
+	sent to init, this option will make init kill the processes
+	that have been removed.
+
+config BUSYBOX_CONFIG_FEATURE_KILL_DELAY
+	int "How long to wait between TERM and KILL (0 - send TERM only)" if FEATURE_KILL_REMOVED
+	range 0 1024
+	default BUSYBOX_DEFAULT_FEATURE_KILL_DELAY
+	depends on BUSYBOX_CONFIG_FEATURE_KILL_REMOVED
+	help
+	With nonzero setting, init sends TERM, forks, child waits N
+	seconds, sends KILL and exits. Setting it too high is unwise
+	(child will hang around for too long and could actually kill
+	the wrong process!)
+
+config BUSYBOX_CONFIG_FEATURE_INIT_SCTTY
+	bool "Run commands with leading dash with controlling tty"
+	default BUSYBOX_DEFAULT_FEATURE_INIT_SCTTY
+	depends on BUSYBOX_CONFIG_INIT || BUSYBOX_CONFIG_LINUXRC
+	help
+	If this option is enabled, init will try to give a controlling
+	tty to any command which has leading hyphen (often it's "-/bin/sh").
+	More precisely, init will do "ioctl(STDIN_FILENO, TIOCSCTTY, 0)".
+	If device attached to STDIN_FILENO can be a ctty but is not yet
+	a ctty for other session, it will become this process' ctty.
+	This is not the traditional init behavour, but is often what you want
+	in an embedded system where the console is only accessed during
+	development or for maintenance.
+	NB: using cttyhack applet may work better.
+
+config BUSYBOX_CONFIG_FEATURE_INIT_SYSLOG
+	bool "Enable init to write to syslog"
+	default BUSYBOX_DEFAULT_FEATURE_INIT_SYSLOG
+	depends on BUSYBOX_CONFIG_INIT || BUSYBOX_CONFIG_LINUXRC
+	help
+	If selected, some init messages are sent to syslog.
+	Otherwise, they are sent to VT #5 if linux virtual tty is detected
+	(if not, no separate logging is done).
+
+config BUSYBOX_CONFIG_FEATURE_INIT_QUIET
+	bool "Be quiet on boot (no 'init started:' message)"
+	default BUSYBOX_DEFAULT_FEATURE_INIT_QUIET
+	depends on BUSYBOX_CONFIG_INIT || BUSYBOX_CONFIG_LINUXRC
+
+config BUSYBOX_CONFIG_FEATURE_INIT_COREDUMPS
+	bool "Support dumping core for child processes (debugging only)"
+	default BUSYBOX_DEFAULT_FEATURE_INIT_COREDUMPS	# not Y because this is a debug option
+	depends on BUSYBOX_CONFIG_INIT || BUSYBOX_CONFIG_LINUXRC
+	help
+	If this option is enabled and the file /.init_enable_core
+	exists, then init will call setrlimit() to allow unlimited
+	core file sizes. If this option is disabled, processes
+	will not generate any core files.
+
+config BUSYBOX_CONFIG_INIT_TERMINAL_TYPE
+	string "Initial terminal type"
+	default BUSYBOX_DEFAULT_INIT_TERMINAL_TYPE
+	depends on BUSYBOX_CONFIG_INIT || BUSYBOX_CONFIG_LINUXRC
+	help
+	This is the initial value set by init for the TERM environment
+	variable. This variable is used by programs which make use of
+	extended terminal capabilities.
+
+	Note that on Linux, init attempts to detect serial terminal and
+	sets TERM to "vt102" if one is found.
+
+config BUSYBOX_CONFIG_FEATURE_INIT_MODIFY_CMDLINE
+	bool "Clear init's command line"
+	default BUSYBOX_DEFAULT_FEATURE_INIT_MODIFY_CMDLINE
+	depends on BUSYBOX_CONFIG_INIT || BUSYBOX_CONFIG_LINUXRC
+	help
+	When launched as PID 1 and after parsing its arguments, init
+	wipes all the arguments but argv[0] and rewrites argv[0] to
+	contain only "init", so that its command line appears solely as
+	"init" in tools such as ps.
+	If this option is set to Y, init will keep its original behavior,
+	otherwise, all the arguments including argv[0] will be preserved,
+	be they parsed or ignored by init.
+	The original command-line used to launch init can then be
+	retrieved in /proc/1/cmdline on Linux, for example.
+
+endmenu
diff --git a/package/utils/busybox/config/klibc-utils/Config.in b/package/utils/busybox/config/klibc-utils/Config.in
new file mode 100644
index 0000000..06b9681
--- /dev/null
+++ b/package/utils/busybox/config/klibc-utils/Config.in
@@ -0,0 +1,42 @@
+# DO NOT EDIT. This file is generated from Config.src
+#
+# For a description of the syntax of this configuration file,
+# see docs/Kconfig-language.txt.
+#
+
+menu "klibc-utils"
+
+config BUSYBOX_CONFIG_MINIPS
+	bool "minips (11 kb)"
+	default BUSYBOX_DEFAULT_MINIPS  # for god's sake, just use "ps" name in your scripts
+	help
+	Alias to "ps".
+config BUSYBOX_CONFIG_NUKE
+	bool "nuke (2.9 kb)"
+	default BUSYBOX_DEFAULT_NUKE  # off by default: too "accidentally destructive"
+	help
+	Alias to "rm -rf".
+config BUSYBOX_CONFIG_RESUME
+	bool "resume (3.2 kb)"
+	default BUSYBOX_DEFAULT_RESUME
+	help
+	Resume from saved "suspend-to-disk" image
+config BUSYBOX_CONFIG_RUN_INIT
+	bool "run-init (7.7 kb)"
+	default BUSYBOX_DEFAULT_RUN_INIT
+	help
+	The run-init utility is used from initramfs to select a new
+	root device. Under initramfs, you have to use this instead of
+	pivot_root.
+
+	Booting with initramfs extracts a gzipped cpio archive into rootfs
+	(which is a variant of ramfs/tmpfs). Because rootfs can't be moved
+	or unmounted, pivot_root will not work from initramfs. Instead,
+	run-init deletes everything out of rootfs (including itself),
+	does a mount --move that overmounts rootfs with the new root, and
+	then execs the specified init program.
+
+	util-linux has a similar tool, switch-root.
+	run-init differs by also having a "-d CAPS_TO_DROP" option.
+
+endmenu
diff --git a/package/utils/busybox/config/libbb/Config.in b/package/utils/busybox/config/libbb/Config.in
new file mode 100644
index 0000000..b3a83b9
--- /dev/null
+++ b/package/utils/busybox/config/libbb/Config.in
@@ -0,0 +1,449 @@
+# DO NOT EDIT. This file is generated from Config.src
+#
+# For a description of the syntax of this configuration file,
+# see docs/Kconfig-language.txt.
+#
+
+comment "Library Tuning"
+
+config BUSYBOX_CONFIG_FEATURE_USE_BSS_TAIL
+	bool "Use the end of BSS page"
+	default BUSYBOX_DEFAULT_FEATURE_USE_BSS_TAIL
+	help
+	Attempt to reclaim a small unused part of BSS.
+
+	Executables have the following parts:
+	= read-only executable code and constants, also known as "text"
+	= read-write data
+	= non-initialized (zeroed on demand) data, also known as "bss"
+
+	At link time, "text" is padded to a full page. At runtime, all "text"
+	pages are mapped RO and executable.
+
+	"Data" starts on the next page boundary, but is not padded
+	to a full page at the end. "Bss" starts wherever "data" ends.
+	At runtime, "data" pages are mapped RW and they are file-backed
+	(this includes a small portion of "bss" which may live in the last
+	partial page of "data").
+	Pages which are fully in "bss" are mapped to anonymous memory.
+
+	"Bss" end is usually not page-aligned. There is an unused space
+	in the last page. Linker marks its start with the "_end" symbol.
+
+	This option will attempt to use that space for bb_common_bufsiz1[]
+	array. If it fits after _end, it will be used, and COMMON_BUFSIZE
+	will be enlarged from its guaranteed minimum size of 1 kbyte.
+	This may require recompilation a second time, since value of _end
+	is known only after final link.
+
+	If you are getting a build error like this:
+		appletlib.c:(.text.main+0xd): undefined reference to '_end'
+	disable this option.
+config BUSYBOX_CONFIG_FLOAT_DURATION
+	bool "Enable fractional duration arguments"
+	default BUSYBOX_DEFAULT_FLOAT_DURATION
+	help
+	Allow sleep N.NNN, top -d N.NNN etc.
+config BUSYBOX_CONFIG_FEATURE_RTMINMAX
+	bool "Support RTMIN[+n] and RTMAX[-n] signal names"
+	default BUSYBOX_DEFAULT_FEATURE_RTMINMAX
+	help
+	Support RTMIN[+n] and RTMAX[-n] signal names
+	in kill, killall etc. This costs ~250 bytes.
+
+config BUSYBOX_CONFIG_FEATURE_RTMINMAX_USE_LIBC_DEFINITIONS
+	bool "Use the definitions of SIGRTMIN/SIGRTMAX provided by libc"
+	default BUSYBOX_DEFAULT_FEATURE_RTMINMAX_USE_LIBC_DEFINITIONS
+	depends on BUSYBOX_CONFIG_FEATURE_RTMINMAX
+	help
+	Some C libraries reserve a few real-time signals for internal
+	use, and adjust the values of SIGRTMIN/SIGRTMAX seen by
+	applications accordingly. Saying yes here means that a signal
+	name RTMIN+n will be interpreted according to the libc definition
+	of SIGRTMIN, and not the raw definition provided by the kernel.
+	This behavior matches "kill -l RTMIN+n" from bash.
+
+choice
+	prompt "Buffer allocation policy"
+	default BUSYBOX_CONFIG_FEATURE_BUFFERS_GO_ON_STACK
+	help
+	There are 3 ways busybox can handle buffer allocations:
+	- Use malloc. This costs code size for the call to xmalloc.
+	- Put them on stack. For some very small machines with limited stack
+	space, this can be deadly. For most folks, this works just fine.
+	- Put them in BSS. This works beautifully for computers with a real
+	MMU (and OS support), but wastes runtime RAM for uCLinux. This
+	behavior was the only one available for versions 0.48 and earlier.
+
+config BUSYBOX_CONFIG_FEATURE_BUFFERS_USE_MALLOC
+	bool "Allocate with Malloc"
+
+config BUSYBOX_CONFIG_FEATURE_BUFFERS_GO_ON_STACK
+	bool "Allocate on the Stack"
+
+config BUSYBOX_CONFIG_FEATURE_BUFFERS_GO_IN_BSS
+	bool "Allocate in the .bss section"
+
+endchoice
+
+config BUSYBOX_CONFIG_PASSWORD_MINLEN
+	int "Minimum password length"
+	default BUSYBOX_DEFAULT_PASSWORD_MINLEN
+	range 5 32
+	help
+	Minimum allowable password length.
+
+config BUSYBOX_CONFIG_MD5_SMALL
+	int "MD5: Trade bytes for speed (0:fast, 3:slow)"
+	default BUSYBOX_DEFAULT_MD5_SMALL  # all "fast or small" options default to small
+	range 0 3
+	help
+	Trade binary size versus speed for the md5 algorithm.
+	Approximate values running uClibc and hashing
+	linux-2.4.4.tar.bz2 were:
+	value           user times (sec)  text size (386)
+	0 (fastest)     1.1               6144
+	1               1.4               5392
+	2               3.0               5088
+	3 (smallest)    5.1               4912
+
+config BUSYBOX_CONFIG_SHA1_SMALL
+	int "SHA1: Trade bytes for speed (0:fast, 3:slow)"
+	default BUSYBOX_DEFAULT_SHA1_SMALL  # all "fast or small" options default to small
+	range 0 3
+	help
+	Trade binary size versus speed for the sha1 algorithm.
+	With FEATURE_COPYBUF_KB=64:
+	                throughput MB/s   size of sha1_process_block64
+	value           486  x86-64       486   x86-64
+	0               440  485          3481  3502
+	1               265  265           641   696
+	2,3             220  210           342   364
+
+config BUSYBOX_CONFIG_SHA1_HWACCEL
+	bool "SHA1: Use hardware accelerated instructions if possible"
+	default BUSYBOX_DEFAULT_SHA1_HWACCEL
+	help
+	On x86, this adds ~590 bytes of code. Throughput
+	is about twice as fast as fully-unrolled generic code.
+
+config BUSYBOX_CONFIG_SHA256_HWACCEL
+	bool "SHA256: Use hardware accelerated instructions if possible"
+	default BUSYBOX_DEFAULT_SHA256_HWACCEL
+	help
+	On x86, this adds ~1k bytes of code.
+
+config BUSYBOX_CONFIG_SHA3_SMALL
+	int "SHA3: Trade bytes for speed (0:fast, 1:slow)"
+	default BUSYBOX_DEFAULT_SHA3_SMALL  # all "fast or small" options default to small
+	range 0 1
+	help
+	Trade binary size versus speed for the sha3 algorithm.
+	SHA3_SMALL=0 compared to SHA3_SMALL=1 (approximate):
+	64-bit x86: +270 bytes of code, 45% faster
+	32-bit x86: +450 bytes of code, 75% faster
+
+config BUSYBOX_CONFIG_FEATURE_NON_POSIX_CP
+	bool "Non-POSIX, but safer, copying to special nodes"
+	default BUSYBOX_DEFAULT_FEATURE_NON_POSIX_CP
+	help
+	With this option, "cp file symlink" will delete symlink
+	and create a regular file. This does not conform to POSIX,
+	but prevents a symlink attack.
+	Similarly, "cp file device" will not send file's data
+	to the device. (To do that, use "cat file >device")
+
+config BUSYBOX_CONFIG_FEATURE_VERBOSE_CP_MESSAGE
+	bool "Give more precise messages when copy fails (cp, mv etc)"
+	default BUSYBOX_DEFAULT_FEATURE_VERBOSE_CP_MESSAGE
+	help
+	Error messages with this feature enabled:
+
+	$ cp file /does_not_exist/file
+	cp: cannot create '/does_not_exist/file': Path does not exist
+	$ cp file /vmlinuz/file
+	cp: cannot stat '/vmlinuz/file': Path has non-directory component
+
+	If this feature is not enabled, they will be, respectively:
+
+	cp: cannot create '/does_not_exist/file': No such file or directory
+	cp: cannot stat '/vmlinuz/file': Not a directory
+
+	This will cost you ~60 bytes.
+
+config BUSYBOX_CONFIG_FEATURE_USE_SENDFILE
+	bool "Use sendfile system call"
+	default BUSYBOX_DEFAULT_FEATURE_USE_SENDFILE
+	help
+	When enabled, busybox will use the kernel sendfile() function
+	instead of read/write loops to copy data between file descriptors
+	(for example, cp command does this a lot).
+	If sendfile() doesn't work, copying code falls back to read/write
+	loop. sendfile() was originally implemented for faster I/O
+	from files to sockets, but since Linux 2.6.33 it was extended
+	to work for many more file types.
+
+config BUSYBOX_CONFIG_FEATURE_COPYBUF_KB
+	int "Copy buffer size, in kilobytes"
+	range 1 1024
+	default BUSYBOX_DEFAULT_FEATURE_COPYBUF_KB
+	help
+	Size of buffer used by cp, mv, install, wget etc.
+	Buffers which are 4 kb or less will be allocated on stack.
+	Bigger buffers will be allocated with mmap, with fallback to 4 kb
+	stack buffer if mmap fails.
+
+config BUSYBOX_CONFIG_MONOTONIC_SYSCALL
+	bool "Use clock_gettime(CLOCK_MONOTONIC) syscall"
+	default BUSYBOX_DEFAULT_MONOTONIC_SYSCALL
+	help
+	Use clock_gettime(CLOCK_MONOTONIC) syscall for measuring
+	time intervals (time, ping, traceroute etc need this).
+	Probably requires Linux 2.6+. If not selected, gettimeofday
+	will be used instead (which gives wrong results if date/time
+	is reset).
+
+config BUSYBOX_CONFIG_IOCTL_HEX2STR_ERROR
+	bool "Use ioctl names rather than hex values in error messages"
+	default BUSYBOX_DEFAULT_IOCTL_HEX2STR_ERROR
+	help
+	Use ioctl names rather than hex values in error messages
+	(e.g. VT_DISALLOCATE rather than 0x5608). If disabled this
+	saves about 1400 bytes.
+
+config BUSYBOX_CONFIG_FEATURE_EDITING
+	bool "Command line editing"
+	default BUSYBOX_DEFAULT_FEATURE_EDITING
+	help
+	Enable line editing (mainly for shell command line).
+
+config BUSYBOX_CONFIG_FEATURE_EDITING_MAX_LEN
+	int "Maximum length of input"
+	range 128 8192
+	default BUSYBOX_DEFAULT_FEATURE_EDITING_MAX_LEN
+	depends on BUSYBOX_CONFIG_FEATURE_EDITING
+	help
+	Line editing code uses on-stack buffers for storage.
+	You may want to decrease this parameter if your target machine
+	benefits from smaller stack usage.
+
+config BUSYBOX_CONFIG_FEATURE_EDITING_VI
+	bool "vi-style line editing commands"
+	default BUSYBOX_DEFAULT_FEATURE_EDITING_VI
+	depends on BUSYBOX_CONFIG_FEATURE_EDITING
+	help
+	Enable vi-style line editing. In shells, this mode can be
+	turned on and off with "set -o vi" and "set +o vi".
+
+config BUSYBOX_CONFIG_FEATURE_EDITING_HISTORY
+	int "History size"
+	# Don't allow way too big values here, code uses fixed "char *history[N]" struct member
+	range 0 9999
+	default BUSYBOX_DEFAULT_FEATURE_EDITING_HISTORY
+	depends on BUSYBOX_CONFIG_FEATURE_EDITING
+	help
+	Specify command history size (0 - disable).
+
+config BUSYBOX_CONFIG_FEATURE_EDITING_SAVEHISTORY
+	bool "History saving"
+	default BUSYBOX_DEFAULT_FEATURE_EDITING_SAVEHISTORY
+	depends on BUSYBOX_CONFIG_FEATURE_EDITING
+	help
+	Enable history saving in shells.
+
+config BUSYBOX_CONFIG_FEATURE_EDITING_SAVE_ON_EXIT
+	bool "Save history on shell exit, not after every command"
+	default BUSYBOX_DEFAULT_FEATURE_EDITING_SAVE_ON_EXIT
+	depends on BUSYBOX_CONFIG_FEATURE_EDITING_SAVEHISTORY
+	help
+	Save history on shell exit, not after every command.
+
+config BUSYBOX_CONFIG_FEATURE_REVERSE_SEARCH
+	bool "Reverse history search"
+	default BUSYBOX_DEFAULT_FEATURE_REVERSE_SEARCH
+	depends on BUSYBOX_CONFIG_FEATURE_EDITING
+	help
+	Enable readline-like Ctrl-R combination for reverse history search.
+	Increases code by about 0.5k.
+
+config BUSYBOX_CONFIG_FEATURE_TAB_COMPLETION
+	bool "Tab completion"
+	default BUSYBOX_DEFAULT_FEATURE_TAB_COMPLETION
+	depends on BUSYBOX_CONFIG_FEATURE_EDITING
+
+config BUSYBOX_CONFIG_FEATURE_USERNAME_COMPLETION
+	bool "Username completion"
+	default BUSYBOX_DEFAULT_FEATURE_USERNAME_COMPLETION
+	depends on BUSYBOX_CONFIG_FEATURE_TAB_COMPLETION
+
+config BUSYBOX_CONFIG_FEATURE_EDITING_FANCY_PROMPT
+	bool "Fancy shell prompts"
+	default BUSYBOX_DEFAULT_FEATURE_EDITING_FANCY_PROMPT
+	depends on BUSYBOX_CONFIG_FEATURE_EDITING
+	help
+	Setting this option allows for prompts to use things like \w and
+	\$ and escape codes.
+
+config BUSYBOX_CONFIG_FEATURE_EDITING_WINCH
+	bool "Enable automatic tracking of window size changes"
+	default BUSYBOX_DEFAULT_FEATURE_EDITING_WINCH
+	depends on BUSYBOX_CONFIG_FEATURE_EDITING
+
+config BUSYBOX_CONFIG_FEATURE_EDITING_ASK_TERMINAL
+	bool "Query cursor position from terminal"
+	default BUSYBOX_DEFAULT_FEATURE_EDITING_ASK_TERMINAL
+	depends on BUSYBOX_CONFIG_FEATURE_EDITING
+	help
+	Allow usage of "ESC [ 6 n" sequence. Terminal answers back with
+	current cursor position. This information is used to make line
+	editing more robust in some cases.
+	If you are not sure whether your terminals respond to this code
+	correctly, or want to save on code size (about 400 bytes),
+	then do not turn this option on.
+
+config BUSYBOX_CONFIG_LOCALE_SUPPORT
+	bool "Enable locale support (system needs locale for this to work)"
+	default BUSYBOX_DEFAULT_LOCALE_SUPPORT
+	help
+	Enable this if your system has locale support and you would like
+	busybox to support locale settings.
+
+config BUSYBOX_CONFIG_UNICODE_SUPPORT
+	bool "Support Unicode"
+	default BUSYBOX_DEFAULT_UNICODE_SUPPORT
+	help
+	This makes various applets aware that one byte is not
+	one character on screen.
+
+	Busybox aims to eventually work correctly with Unicode displays.
+	Any older encodings are not guaranteed to work.
+	Probably by the time when busybox will be fully Unicode-clean,
+	other encodings will be mainly of historic interest.
+
+config BUSYBOX_CONFIG_UNICODE_USING_LOCALE
+	bool "Use libc routines for Unicode (else uses internal ones)"
+	default BUSYBOX_DEFAULT_UNICODE_USING_LOCALE
+	depends on BUSYBOX_CONFIG_UNICODE_SUPPORT && BUSYBOX_CONFIG_LOCALE_SUPPORT
+	help
+	With this option on, Unicode support is implemented using libc
+	routines. Otherwise, internal implementation is used.
+	Internal implementation is smaller.
+
+config BUSYBOX_CONFIG_FEATURE_CHECK_UNICODE_IN_ENV
+	bool "Check $LC_ALL, $LC_CTYPE and $LANG environment variables"
+	default BUSYBOX_DEFAULT_FEATURE_CHECK_UNICODE_IN_ENV
+	depends on BUSYBOX_CONFIG_UNICODE_SUPPORT && !BUSYBOX_CONFIG_UNICODE_USING_LOCALE
+	help
+	With this option on, Unicode support is activated
+	only if locale-related variables have the value of the form
+	"xxxx.utf8"
+
+	Otherwise, Unicode support will be always enabled and active.
+
+config BUSYBOX_CONFIG_SUBST_WCHAR
+	int "Character code to substitute unprintable characters with"
+	depends on BUSYBOX_CONFIG_UNICODE_SUPPORT
+	default BUSYBOX_DEFAULT_SUBST_WCHAR
+	help
+	Typical values are 63 for '?' (works with any output device),
+	30 for ASCII substitute control code,
+	65533 (0xfffd) for Unicode replacement character.
+
+config BUSYBOX_CONFIG_LAST_SUPPORTED_WCHAR
+	int "Range of supported Unicode characters"
+	depends on BUSYBOX_CONFIG_UNICODE_SUPPORT
+	default BUSYBOX_DEFAULT_LAST_SUPPORTED_WCHAR
+	help
+	Any character with Unicode value bigger than this is assumed
+	to be non-printable on output device. Many applets replace
+	such characters with substitution character.
+
+	The idea is that many valid printable Unicode chars
+	nevertheless are not displayed correctly. Think about
+	combining charachers, double-wide hieroglyphs, obscure
+	characters in dozens of ancient scripts...
+	Many terminals, terminal emulators, xterms etc will fail
+	to handle them correctly. Choose the smallest value
+	which suits your needs.
+
+	Typical values are:
+	126 - ASCII only
+	767 (0x2ff) - there are no combining chars in [0..767] range
+			(the range includes Latin 1, Latin Ext. A and B),
+			code is ~700 bytes smaller for this case.
+	4351 (0x10ff) - there are no double-wide chars in [0..4351] range,
+			code is ~300 bytes smaller for this case.
+	12799 (0x31ff) - nearly all non-ideographic characters are
+			available in [0..12799] range, including
+			East Asian scripts like katakana, hiragana, hangul,
+			bopomofo...
+	0 - off, any valid printable Unicode character will be printed.
+
+config BUSYBOX_CONFIG_UNICODE_COMBINING_WCHARS
+	bool "Allow zero-width Unicode characters on output"
+	default BUSYBOX_DEFAULT_UNICODE_COMBINING_WCHARS
+	depends on BUSYBOX_CONFIG_UNICODE_SUPPORT
+	help
+	With this option off, any Unicode char with width of 0
+	is substituted on output.
+
+config BUSYBOX_CONFIG_UNICODE_WIDE_WCHARS
+	bool "Allow wide Unicode characters on output"
+	default BUSYBOX_DEFAULT_UNICODE_WIDE_WCHARS
+	depends on BUSYBOX_CONFIG_UNICODE_SUPPORT
+	help
+	With this option off, any Unicode char with width > 1
+	is substituted on output.
+
+config BUSYBOX_CONFIG_UNICODE_BIDI_SUPPORT
+	bool "Bidirectional character-aware line input"
+	default BUSYBOX_DEFAULT_UNICODE_BIDI_SUPPORT
+	depends on BUSYBOX_CONFIG_UNICODE_SUPPORT && !BUSYBOX_CONFIG_UNICODE_USING_LOCALE
+	help
+	With this option on, right-to-left Unicode characters
+	are treated differently on input (e.g. cursor movement).
+
+config BUSYBOX_CONFIG_UNICODE_NEUTRAL_TABLE
+	bool "In bidi input, support non-ASCII neutral chars too"
+	default BUSYBOX_DEFAULT_UNICODE_NEUTRAL_TABLE
+	depends on BUSYBOX_CONFIG_UNICODE_BIDI_SUPPORT
+	help
+	In most cases it's enough to treat only ASCII non-letters
+	(i.e. punctuation, numbers and space) as characters
+	with neutral directionality.
+	With this option on, more extensive (and bigger) table
+	of neutral chars will be used.
+
+config BUSYBOX_CONFIG_UNICODE_PRESERVE_BROKEN
+	bool "Make it possible to enter sequences of chars which are not Unicode"
+	default BUSYBOX_DEFAULT_UNICODE_PRESERVE_BROKEN
+	depends on BUSYBOX_CONFIG_UNICODE_SUPPORT
+	help
+	With this option on, on line-editing input (such as used by shells)
+	invalid UTF-8 bytes are not substituted with the selected
+	substitution character.
+	For example, this means that entering 'l', 's', ' ', 0xff, [Enter]
+	at shell prompt will list file named 0xff (single char name
+	with char value 255), not file named '?'.
+
+choice
+	prompt "Use LOOP_CONFIGURE for losetup and loop mounts"
+	default BUSYBOX_CONFIG_TRY_LOOP_CONFIGURE
+	help
+	LOOP_CONFIGURE is added to Linux 5.8
+	https://lwn.net/Articles/820408/
+	This allows userspace to completely setup a loop device with a single
+	ioctl, removing the in-between state where the device can be partially
+	configured - eg the loop device has a backing file associated with it,
+	but is reading from the wrong offset.
+
+config BUSYBOX_CONFIG_LOOP_CONFIGURE
+	bool "use LOOP_CONFIGURE, needs kernel >= 5.8"
+
+config BUSYBOX_CONFIG_NO_LOOP_CONFIGURE
+	bool "use LOOP_SET_FD + LOOP_SET_STATUS"
+
+config BUSYBOX_CONFIG_TRY_LOOP_CONFIGURE
+	bool "try LOOP_CONFIGURE, fall back to LOOP_SET_FD + LOOP_SET_STATUS"
+
+endchoice
diff --git a/package/utils/busybox/config/loginutils/Config.in b/package/utils/busybox/config/loginutils/Config.in
new file mode 100644
index 0000000..465fa51
--- /dev/null
+++ b/package/utils/busybox/config/loginutils/Config.in
@@ -0,0 +1,330 @@
+# DO NOT EDIT. This file is generated from Config.src
+#
+# For a description of the syntax of this configuration file,
+# see docs/Kconfig-language.txt.
+#
+
+menu "Login/Password Management Utilities"
+
+config BUSYBOX_CONFIG_FEATURE_SHADOWPASSWDS
+	bool "Support shadow passwords"
+	default BUSYBOX_DEFAULT_FEATURE_SHADOWPASSWDS
+	help
+	Build support for shadow password in /etc/shadow. This file is only
+	readable by root and thus the encrypted passwords are no longer
+	publicly readable.
+
+config BUSYBOX_CONFIG_USE_BB_PWD_GRP
+	bool "Use internal password and group functions rather than system functions"
+	default BUSYBOX_DEFAULT_USE_BB_PWD_GRP
+	help
+	If you leave this disabled, busybox will use the system's password
+	and group functions. And if you are using the GNU C library
+	(glibc), you will then need to install the /etc/nsswitch.conf
+	configuration file and the required /lib/libnss_* libraries in
+	order for the password and group functions to work. This generally
+	makes your embedded system quite a bit larger.
+
+	Enabling this option will cause busybox to directly access the
+	system's /etc/password, /etc/group files (and your system will be
+	smaller, and I will get fewer emails asking about how glibc NSS
+	works). When this option is enabled, you will not be able to use
+	PAM to access remote LDAP password servers and whatnot. And if you
+	want hostname resolution to work with glibc, you still need the
+	/lib/libnss_* libraries.
+
+	If you need to use glibc's nsswitch.conf mechanism
+	(e.g. if user/group database is NOT stored in /etc/passwd etc),
+	you must NOT use this option.
+
+	If you enable this option, it will add about 1.5k.
+
+config BUSYBOX_CONFIG_USE_BB_SHADOW
+	bool "Use internal shadow password functions"
+	default BUSYBOX_DEFAULT_USE_BB_SHADOW
+	depends on BUSYBOX_CONFIG_USE_BB_PWD_GRP && BUSYBOX_CONFIG_FEATURE_SHADOWPASSWDS
+	help
+	If you leave this disabled, busybox will use the system's shadow
+	password handling functions. And if you are using the GNU C library
+	(glibc), you will then need to install the /etc/nsswitch.conf
+	configuration file and the required /lib/libnss_* libraries in
+	order for the shadow password functions to work. This generally
+	makes your embedded system quite a bit larger.
+
+	Enabling this option will cause busybox to directly access the
+	system's /etc/shadow file when handling shadow passwords. This
+	makes your system smaller (and I will get fewer emails asking about
+	how glibc NSS works). When this option is enabled, you will not be
+	able to use PAM to access shadow passwords from remote LDAP
+	password servers and whatnot.
+
+config BUSYBOX_CONFIG_USE_BB_CRYPT
+	bool "Use internal crypt functions"
+	default BUSYBOX_DEFAULT_USE_BB_CRYPT
+	help
+	Busybox has internal DES and MD5 crypt functions.
+	They produce results which are identical to corresponding
+	standard C library functions.
+
+	If you leave this disabled, busybox will use the system's
+	crypt functions. Most C libraries use large (~70k)
+	static buffers there, and also combine them with more general
+	DES encryption/decryption.
+
+	For busybox, having large static buffers is undesirable,
+	especially on NOMMU machines. Busybox also doesn't need
+	DES encryption/decryption and can do with smaller code.
+
+	If you enable this option, it will add about 4.8k of code
+	if you are building dynamically linked executable.
+	In static build, it makes code _smaller_ by about 1.2k,
+	and likely many kilobytes less of bss.
+
+config BUSYBOX_CONFIG_USE_BB_CRYPT_SHA
+	bool "Enable SHA256/512 crypt functions"
+	default BUSYBOX_DEFAULT_USE_BB_CRYPT_SHA
+	depends on BUSYBOX_CONFIG_USE_BB_CRYPT
+	help
+	Enable this if you have passwords starting with "$5$" or "$6$"
+	in your /etc/passwd or /etc/shadow files. These passwords
+	are hashed using SHA256 and SHA512 algorithms. Support for them
+	was added to glibc in 2008.
+	With this option off, login will fail password check for any
+	user which has password encrypted with these algorithms.
+
+config BUSYBOX_CONFIG_ADD_SHELL
+	bool "add-shell (3.1 kb)"
+	default BUSYBOX_DEFAULT_ADD_SHELL if BUSYBOX_CONFIG_DESKTOP
+	help
+	Add shells to /etc/shells.
+
+config BUSYBOX_CONFIG_REMOVE_SHELL
+	bool "remove-shell (3 kb)"
+	default BUSYBOX_DEFAULT_REMOVE_SHELL if BUSYBOX_CONFIG_DESKTOP
+	help
+	Remove shells from /etc/shells.
+config BUSYBOX_CONFIG_ADDGROUP
+	bool "addgroup (8.6 kb)"
+	default BUSYBOX_DEFAULT_ADDGROUP
+	select BUSYBOX_CONFIG_LONG_OPTS
+	help
+	Utility for creating a new group account.
+
+config BUSYBOX_CONFIG_FEATURE_ADDUSER_TO_GROUP
+	bool "Support adding users to groups"
+	default BUSYBOX_DEFAULT_FEATURE_ADDUSER_TO_GROUP
+	depends on BUSYBOX_CONFIG_ADDGROUP
+	help
+	If called with two non-option arguments,
+	addgroup will add an existing user to an
+	existing group.
+config BUSYBOX_CONFIG_ADDUSER
+	bool "adduser (15 kb)"
+	default BUSYBOX_DEFAULT_ADDUSER
+	select BUSYBOX_CONFIG_LONG_OPTS
+	help
+	Utility for creating a new user account.
+
+config BUSYBOX_CONFIG_FEATURE_CHECK_NAMES
+	bool "Enable sanity check on user/group names in adduser and addgroup"
+	default BUSYBOX_DEFAULT_FEATURE_CHECK_NAMES
+	depends on BUSYBOX_CONFIG_ADDUSER || BUSYBOX_CONFIG_ADDGROUP
+	help
+	Enable sanity check on user and group names in adduser and addgroup.
+	To avoid problems, the user or group name should consist only of
+	letters, digits, underscores, periods, at signs and dashes,
+	and not start with a dash (as defined by IEEE Std 1003.1-2001).
+	For compatibility with Samba machine accounts "$" is also supported
+	at the end of the user or group name.
+
+config BUSYBOX_CONFIG_LAST_ID
+	int "Last valid uid or gid for adduser and addgroup"
+	depends on BUSYBOX_CONFIG_ADDUSER || BUSYBOX_CONFIG_ADDGROUP
+	default BUSYBOX_DEFAULT_LAST_ID
+	help
+	Last valid uid or gid for adduser and addgroup
+
+config BUSYBOX_CONFIG_FIRST_SYSTEM_ID
+	int "First valid system uid or gid for adduser and addgroup"
+	depends on BUSYBOX_CONFIG_ADDUSER || BUSYBOX_CONFIG_ADDGROUP
+	range 0 BUSYBOX_CONFIG_LAST_ID
+	default BUSYBOX_DEFAULT_FIRST_SYSTEM_ID
+	help
+	First valid system uid or gid for adduser and addgroup
+
+config BUSYBOX_CONFIG_LAST_SYSTEM_ID
+	int "Last valid system uid or gid for adduser and addgroup"
+	depends on BUSYBOX_CONFIG_ADDUSER || BUSYBOX_CONFIG_ADDGROUP
+	range BUSYBOX_CONFIG_FIRST_SYSTEM_ID BUSYBOX_CONFIG_LAST_ID
+	default BUSYBOX_DEFAULT_LAST_SYSTEM_ID
+	help
+	Last valid system uid or gid for adduser and addgroup
+config BUSYBOX_CONFIG_CHPASSWD
+	bool "chpasswd (18 kb)"
+	default BUSYBOX_DEFAULT_CHPASSWD
+	help
+	Reads a file of user name and password pairs from standard input
+	and uses this information to update a group of existing users.
+
+config BUSYBOX_CONFIG_FEATURE_DEFAULT_PASSWD_ALGO
+	string "Default encryption method (passwd -a, cryptpw -m, chpasswd -c ALG)"
+	default BUSYBOX_DEFAULT_FEATURE_DEFAULT_PASSWD_ALGO
+	depends on BUSYBOX_CONFIG_PASSWD || BUSYBOX_CONFIG_CRYPTPW || BUSYBOX_CONFIG_CHPASSWD
+	help
+	Possible choices are "d[es]", "m[d5]", "s[ha256]" or "sha512".
+config BUSYBOX_CONFIG_CRYPTPW
+	bool "cryptpw (14 kb)"
+	default BUSYBOX_DEFAULT_CRYPTPW
+	help
+	Encrypts the given password with the crypt(3) libc function
+	using the given salt.
+
+config BUSYBOX_CONFIG_MKPASSWD
+	bool "mkpasswd (15 kb)"
+	default BUSYBOX_DEFAULT_MKPASSWD
+	help
+	Encrypts the given password with the crypt(3) libc function
+	using the given salt. Debian has this utility under mkpasswd
+	name. Busybox provides mkpasswd as an alias for cryptpw.
+config BUSYBOX_CONFIG_DELUSER
+	bool "deluser (9.1 kb)"
+	default BUSYBOX_DEFAULT_DELUSER
+	help
+	Utility for deleting a user account.
+
+config BUSYBOX_CONFIG_DELGROUP
+	bool "delgroup (6.4 kb)"
+	default BUSYBOX_DEFAULT_DELGROUP
+	help
+	Utility for deleting a group account.
+
+config BUSYBOX_CONFIG_FEATURE_DEL_USER_FROM_GROUP
+	bool "Support removing users from groups"
+	default BUSYBOX_DEFAULT_FEATURE_DEL_USER_FROM_GROUP
+	depends on BUSYBOX_CONFIG_DELGROUP
+	help
+	If called with two non-option arguments, deluser
+	or delgroup will remove an user from a specified group.
+config BUSYBOX_CONFIG_GETTY
+	bool "getty (10 kb)"
+	default BUSYBOX_DEFAULT_GETTY
+	select BUSYBOX_CONFIG_FEATURE_SYSLOG
+	help
+	getty lets you log in on a tty. It is normally invoked by init.
+
+	Note that you can save a few bytes by disabling it and
+	using login applet directly.
+	If you need to reset tty attributes before calling login,
+	this script approximates getty:
+
+	exec </dev/$1 >/dev/$1 2>&1 || exit 1
+	reset
+	stty sane; stty ispeed 38400; stty ospeed 38400
+	printf "%s login: " "`hostname`"
+	read -r login
+	exec /bin/login "$login"
+config BUSYBOX_CONFIG_LOGIN
+	bool "login (24 kb)"
+	default BUSYBOX_DEFAULT_LOGIN
+	select BUSYBOX_CONFIG_FEATURE_SYSLOG
+	help
+	login is used when signing onto a system.
+
+	Note that busybox binary must be setuid root for this applet to
+	work properly.
+
+config BUSYBOX_CONFIG_LOGIN_SESSION_AS_CHILD
+	bool "Run logged in session in a child process"
+	default BUSYBOX_DEFAULT_LOGIN_SESSION_AS_CHILD if BUSYBOX_CONFIG_PAM
+	depends on BUSYBOX_CONFIG_LOGIN
+	help
+	Run the logged in session in a child process.  This allows
+	login to clean up things such as utmp entries or PAM sessions
+	when the login session is complete.  If you use PAM, you
+	almost always would want this to be set to Y, else PAM session
+	will not be cleaned up.
+
+config BUSYBOX_CONFIG_LOGIN_SCRIPTS
+	bool "Support login scripts"
+	depends on BUSYBOX_CONFIG_LOGIN
+	default BUSYBOX_DEFAULT_LOGIN_SCRIPTS
+	help
+	Enable this if you want login to execute $LOGIN_PRE_SUID_SCRIPT
+	just prior to switching from root to logged-in user.
+
+config BUSYBOX_CONFIG_FEATURE_NOLOGIN
+	bool "Support /etc/nologin"
+	default BUSYBOX_DEFAULT_FEATURE_NOLOGIN
+	depends on BUSYBOX_CONFIG_LOGIN
+	help
+	The file /etc/nologin is used by (some versions of) login(1).
+	If it exists, non-root logins are prohibited.
+
+config BUSYBOX_CONFIG_FEATURE_SECURETTY
+	bool "Support /etc/securetty"
+	default BUSYBOX_DEFAULT_FEATURE_SECURETTY
+	depends on BUSYBOX_CONFIG_LOGIN
+	help
+	The file /etc/securetty is used by (some versions of) login(1).
+	The file contains the device names of tty lines (one per line,
+	without leading /dev/) on which root is allowed to login.
+config BUSYBOX_CONFIG_PASSWD
+	bool "passwd (21 kb)"
+	default BUSYBOX_DEFAULT_PASSWD
+	select BUSYBOX_CONFIG_FEATURE_SYSLOG
+	help
+	passwd changes passwords for user and group accounts. A normal user
+	may only change the password for his/her own account, the super user
+	may change the password for any account. The administrator of a group
+	may change the password for the group.
+
+	Note that busybox binary must be setuid root for this applet to
+	work properly.
+
+config BUSYBOX_CONFIG_FEATURE_PASSWD_WEAK_CHECK
+	bool "Check new passwords for weakness"
+	default BUSYBOX_DEFAULT_FEATURE_PASSWD_WEAK_CHECK
+	depends on BUSYBOX_CONFIG_PASSWD
+	help
+	With this option passwd will refuse new passwords which are "weak".
+config BUSYBOX_CONFIG_SU
+	bool "su (19 kb)"
+	default BUSYBOX_DEFAULT_SU
+	select BUSYBOX_CONFIG_FEATURE_SYSLOG
+	help
+	su is used to become another user during a login session.
+	Invoked without a username, su defaults to becoming the super user.
+	Note that busybox binary must be setuid root for this applet to
+	work properly.
+
+config BUSYBOX_CONFIG_FEATURE_SU_SYSLOG
+	bool "Log to syslog all attempts to use su"
+	default BUSYBOX_DEFAULT_FEATURE_SU_SYSLOG
+	depends on BUSYBOX_CONFIG_SU
+
+config BUSYBOX_CONFIG_FEATURE_SU_CHECKS_SHELLS
+	bool "If user's shell is not in /etc/shells, disallow -s PROG"
+	default BUSYBOX_DEFAULT_FEATURE_SU_CHECKS_SHELLS
+	depends on BUSYBOX_CONFIG_SU
+
+config BUSYBOX_CONFIG_FEATURE_SU_BLANK_PW_NEEDS_SECURE_TTY
+	bool "Allow blank passwords only on TTYs in /etc/securetty"
+	default BUSYBOX_DEFAULT_FEATURE_SU_BLANK_PW_NEEDS_SECURE_TTY
+	depends on BUSYBOX_CONFIG_SU
+config BUSYBOX_CONFIG_SULOGIN
+	bool "sulogin (17 kb)"
+	default BUSYBOX_DEFAULT_SULOGIN
+	select BUSYBOX_CONFIG_FEATURE_SYSLOG
+	help
+	sulogin is invoked when the system goes into single user
+	mode (this is done through an entry in inittab).
+config BUSYBOX_CONFIG_VLOCK
+	bool "vlock (17 kb)"
+	default BUSYBOX_DEFAULT_VLOCK
+	help
+	Build the "vlock" applet which allows you to lock (virtual) terminals.
+
+	Note that busybox binary must be setuid root for this applet to
+	work properly.
+
+endmenu
diff --git a/package/utils/busybox/config/mailutils/Config.in b/package/utils/busybox/config/mailutils/Config.in
new file mode 100644
index 0000000..ea7ae6d
--- /dev/null
+++ b/package/utils/busybox/config/mailutils/Config.in
@@ -0,0 +1,51 @@
+# DO NOT EDIT. This file is generated from Config.src
+menu "Mail Utilities"
+
+config BUSYBOX_CONFIG_FEATURE_MIME_CHARSET
+	string "Default charset"
+	default BUSYBOX_DEFAULT_FEATURE_MIME_CHARSET
+	depends on BUSYBOX_CONFIG_MAKEMIME || BUSYBOX_CONFIG_REFORMIME || BUSYBOX_CONFIG_SENDMAIL
+	help
+	Default charset of the message.
+
+config BUSYBOX_CONFIG_MAKEMIME
+	bool "makemime (5.4 kb)"
+	default BUSYBOX_DEFAULT_MAKEMIME
+	help
+	Create MIME-formatted messages.
+config BUSYBOX_CONFIG_POPMAILDIR
+	bool "popmaildir (10 kb)"
+	default BUSYBOX_DEFAULT_POPMAILDIR
+	help
+	Simple yet powerful POP3 mail popper. Delivers content
+	of remote mailboxes to local Maildir.
+
+config BUSYBOX_CONFIG_FEATURE_POPMAILDIR_DELIVERY
+	bool "Allow message filters and custom delivery program"
+	default BUSYBOX_DEFAULT_FEATURE_POPMAILDIR_DELIVERY
+	depends on BUSYBOX_CONFIG_POPMAILDIR
+	help
+	Allow to use a custom program to filter the content
+	of the message before actual delivery (-F "prog [args...]").
+	Allow to use a custom program for message actual delivery
+	(-M "prog [args...]").
+config BUSYBOX_CONFIG_REFORMIME
+	bool "reformime (7.5 kb)"
+	default BUSYBOX_DEFAULT_REFORMIME
+	help
+	Parse MIME-formatted messages.
+
+config BUSYBOX_CONFIG_FEATURE_REFORMIME_COMPAT
+	bool "Accept and ignore options other than -x and -X"
+	default BUSYBOX_DEFAULT_FEATURE_REFORMIME_COMPAT
+	depends on BUSYBOX_CONFIG_REFORMIME
+	help
+	Accept (for compatibility only) and ignore options
+	other than -x and -X.
+config BUSYBOX_CONFIG_SENDMAIL
+	bool "sendmail (14 kb)"
+	default BUSYBOX_DEFAULT_SENDMAIL
+	help
+	Barebones sendmail.
+
+endmenu
diff --git a/package/utils/busybox/config/miscutils/Config.in b/package/utils/busybox/config/miscutils/Config.in
new file mode 100644
index 0000000..e15e318
--- /dev/null
+++ b/package/utils/busybox/config/miscutils/Config.in
@@ -0,0 +1,824 @@
+# DO NOT EDIT. This file is generated from Config.src
+#
+# For a description of the syntax of this configuration file,
+# see docs/Kconfig-language.txt.
+#
+
+menu "Miscellaneous Utilities"
+
+config BUSYBOX_CONFIG_ADJTIMEX
+	bool "adjtimex (4.7 kb)"
+	default BUSYBOX_DEFAULT_ADJTIMEX
+	help
+	Adjtimex reads and optionally sets adjustment parameters for
+	the Linux clock adjustment algorithm.
+config BUSYBOX_CONFIG_ASCII
+	bool "ascii"
+	default BUSYBOX_DEFAULT_ASCII
+	help
+	Print ascii table.
+
+config BUSYBOX_CONFIG_BBCONFIG
+	bool "bbconfig (9.7 kb)"
+	default BUSYBOX_DEFAULT_BBCONFIG
+	help
+	The bbconfig applet will print the config file with which
+	busybox was built.
+
+config BUSYBOX_CONFIG_FEATURE_COMPRESS_BBCONFIG
+	bool "Compress bbconfig data"
+	default BUSYBOX_DEFAULT_FEATURE_COMPRESS_BBCONFIG
+	depends on BUSYBOX_CONFIG_BBCONFIG
+	help
+	Store bbconfig data in compressed form, uncompress them on-the-fly
+	before output.
+
+	If you have a really tiny busybox with few applets enabled (and
+	bunzip2 isn't one of them), the overhead of the decompressor might
+	be noticeable. Also, if you run executables directly from ROM
+	and have very little memory, this might not be a win. Otherwise,
+	you probably want this.
+config BUSYBOX_CONFIG_BC
+	bool "bc (45 kb)"
+	default BUSYBOX_DEFAULT_BC
+	select BUSYBOX_CONFIG_FEATURE_DC_BIG
+	help
+	bc is a command-line, arbitrary-precision calculator with a
+	Turing-complete language. See the GNU bc manual
+	(https://www.gnu.org/software/bc/manual/bc.html) and bc spec
+	(http://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html).
+
+	This bc has five differences to the GNU bc:
+	  1) The period (.) is a shortcut for "last", as in the BSD bc.
+	  2) Arrays are copied before being passed as arguments to
+	     functions. This behavior is required by the bc spec.
+	  3) Arrays can be passed to the builtin "length" function to get
+	     the number of elements in the array. This prints "1":
+		a[0] = 0; length(a[])
+	  4) The precedence of the boolean "not" operator (!) is equal to
+	     that of the unary minus (-) negation operator. This still
+	     allows POSIX-compliant scripts to work while somewhat
+	     preserving expected behavior (versus C) and making parsing
+	     easier.
+	  5) "read()" accepts expressions, not only numeric literals.
+
+config BUSYBOX_CONFIG_DC
+	bool "dc (36 kb)"
+	default BUSYBOX_DEFAULT_DC
+	help
+	dc is a reverse-polish notation command-line calculator which
+	supports unlimited precision arithmetic. See the FreeBSD man page
+	(https://www.unix.com/man-page/FreeBSD/1/dc/) and GNU dc manual
+	(https://www.gnu.org/software/bc/manual/dc-1.05/html_mono/dc.html).
+
+	This dc has a few differences from the two above:
+	  1) When printing a byte stream (command "P"), this dc follows what
+	     the FreeBSD dc does.
+	  2) Implements the GNU extensions for divmod ("~") and
+	     modular exponentiation ("|").
+	  3) Implements all FreeBSD extensions, except for "J" and "M".
+	  4) Like the FreeBSD dc, this dc supports extended registers.
+	     However, they are implemented differently. When it encounters
+	     whitespace where a register should be, it skips the whitespace.
+	     If the character following is not a lowercase letter, an error
+	     is issued. Otherwise, the register name is parsed by the
+	     following regex: [a-z][a-z0-9_]*
+	     This generally means that register names will be surrounded by
+	     whitespace. Examples:
+		l idx s temp L index S temp2 < do_thing
+	     Also note that, like the FreeBSD dc, extended registers are not
+	     allowed unless the "-x" option is given.
+
+if BC || BUSYBOX_CONFIG_DC  # for menuconfig indenting
+
+config BUSYBOX_CONFIG_FEATURE_DC_BIG
+	bool "Use bc code base for dc (larger, more features)"
+	default BUSYBOX_DEFAULT_FEATURE_DC_BIG
+
+config BUSYBOX_CONFIG_FEATURE_DC_LIBM
+	bool "Enable power and exp functions (requires libm)"
+	default BUSYBOX_DEFAULT_FEATURE_DC_LIBM
+	depends on BUSYBOX_CONFIG_DC && !BUSYBOX_CONFIG_BC && !BUSYBOX_CONFIG_FEATURE_DC_BIG
+	help
+	Enable power and exp functions.
+	NOTE: This will require libm to be present for linking.
+
+config BUSYBOX_CONFIG_FEATURE_BC_INTERACTIVE
+	bool "Interactive mode (+4kb)"
+	default BUSYBOX_DEFAULT_FEATURE_BC_INTERACTIVE
+	depends on BUSYBOX_CONFIG_BC || (BUSYBOX_CONFIG_DC && BUSYBOX_CONFIG_FEATURE_DC_BIG)
+	help
+	Enable interactive mode: when started on a tty,
+	^C interrupts execution and returns to command line,
+	errors also return to command line instead of exiting,
+	line editing with history is available.
+
+	With this option off, input can still be taken from tty,
+	but all errors are fatal, ^C is fatal,
+	tty is treated exactly the same as any other
+	standard input (IOW: no line editing).
+
+config BUSYBOX_CONFIG_FEATURE_BC_LONG_OPTIONS
+	bool "Enable bc/dc long options"
+	default BUSYBOX_DEFAULT_FEATURE_BC_LONG_OPTIONS
+	depends on BUSYBOX_CONFIG_BC || (BUSYBOX_CONFIG_DC && BUSYBOX_CONFIG_FEATURE_DC_BIG)
+
+endif
+config BUSYBOX_CONFIG_BEEP
+	bool "beep (2.4 kb)"
+	default BUSYBOX_DEFAULT_BEEP
+	help
+	The beep applets beeps in a given freq/Hz.
+
+config BUSYBOX_CONFIG_FEATURE_BEEP_FREQ
+	int "default frequency"
+	range 20 50000	# allowing 0 here breaks the build
+	default BUSYBOX_DEFAULT_FEATURE_BEEP_FREQ
+	depends on BUSYBOX_CONFIG_BEEP
+	help
+	Frequency for default beep.
+
+config BUSYBOX_CONFIG_FEATURE_BEEP_LENGTH_MS
+	int "default length"
+	range 0 2147483647
+	default BUSYBOX_DEFAULT_FEATURE_BEEP_LENGTH_MS
+	depends on BUSYBOX_CONFIG_BEEP
+	help
+	Length in ms for default beep.
+config BUSYBOX_CONFIG_CHAT
+	bool "chat (6.3 kb)"
+	default BUSYBOX_DEFAULT_CHAT
+	help
+	Simple chat utility.
+
+config BUSYBOX_CONFIG_FEATURE_CHAT_NOFAIL
+	bool "Enable NOFAIL expect strings"
+	depends on BUSYBOX_CONFIG_CHAT
+	default BUSYBOX_DEFAULT_FEATURE_CHAT_NOFAIL
+	help
+	When enabled expect strings which are started with a dash trigger
+	no-fail mode. That is when expectation is not met within timeout
+	the script is not terminated but sends next SEND string and waits
+	for next EXPECT string. This allows to compose far more flexible
+	scripts.
+
+config BUSYBOX_CONFIG_FEATURE_CHAT_TTY_HIFI
+	bool "Force STDIN to be a TTY"
+	depends on BUSYBOX_CONFIG_CHAT
+	default BUSYBOX_DEFAULT_FEATURE_CHAT_TTY_HIFI
+	help
+	Original chat always treats STDIN as a TTY device and sets for it
+	so-called raw mode. This option turns on such behaviour.
+
+config BUSYBOX_CONFIG_FEATURE_CHAT_IMPLICIT_CR
+	bool "Enable implicit Carriage Return"
+	depends on BUSYBOX_CONFIG_CHAT
+	default BUSYBOX_DEFAULT_FEATURE_CHAT_IMPLICIT_CR
+	help
+	When enabled make chat to terminate all SEND strings with a "\r"
+	unless "\c" is met anywhere in the string.
+
+config BUSYBOX_CONFIG_FEATURE_CHAT_SWALLOW_OPTS
+	bool "Swallow options"
+	depends on BUSYBOX_CONFIG_CHAT
+	default BUSYBOX_DEFAULT_FEATURE_CHAT_SWALLOW_OPTS
+	help
+	Busybox chat require no options. To make it not fail when used
+	in place of original chat (which has a bunch of options) turn
+	this on.
+
+config BUSYBOX_CONFIG_FEATURE_CHAT_SEND_ESCAPES
+	bool "Support weird SEND escapes"
+	depends on BUSYBOX_CONFIG_CHAT
+	default BUSYBOX_DEFAULT_FEATURE_CHAT_SEND_ESCAPES
+	help
+	Original chat uses some escape sequences in SEND arguments which
+	are not sent to device but rather performs special actions.
+	E.g. "\K" means to send a break sequence to device.
+	"\d" delays execution for a second, "\p" -- for a 1/100 of second.
+	Before turning this option on think twice: do you really need them?
+
+config BUSYBOX_CONFIG_FEATURE_CHAT_VAR_ABORT_LEN
+	bool "Support variable-length ABORT conditions"
+	depends on BUSYBOX_CONFIG_CHAT
+	default BUSYBOX_DEFAULT_FEATURE_CHAT_VAR_ABORT_LEN
+	help
+	Original chat uses fixed 50-bytes length ABORT conditions. Say N here.
+
+config BUSYBOX_CONFIG_FEATURE_CHAT_CLR_ABORT
+	bool "Support revoking of ABORT conditions"
+	depends on BUSYBOX_CONFIG_CHAT
+	default BUSYBOX_DEFAULT_FEATURE_CHAT_CLR_ABORT
+	help
+	Support CLR_ABORT directive.
+config BUSYBOX_CONFIG_CONSPY
+	bool "conspy (10 kb)"
+	default BUSYBOX_DEFAULT_CONSPY
+	help
+	A text-mode VNC like program for Linux virtual terminals.
+	example:  conspy NUM      shared access to console num
+	or        conspy -nd NUM  screenshot of console num
+	or        conspy -cs NUM  poor man's GNU screen like
+config BUSYBOX_CONFIG_CROND
+	bool "crond (14 kb)"
+	default BUSYBOX_DEFAULT_CROND
+	select BUSYBOX_CONFIG_FEATURE_SYSLOG
+	help
+	Crond is a background daemon that parses individual crontab
+	files and executes commands on behalf of the users in question.
+	This is a port of dcron from slackware. It uses files of the
+	format /var/spool/cron/crontabs/<username> files, for example:
+		$ cat /var/spool/cron/crontabs/root
+		# Run daily cron jobs at 4:40 every day:
+		40 4 * * * /etc/cron/daily > /dev/null 2>&1
+
+config BUSYBOX_CONFIG_FEATURE_CROND_D
+	bool "Support -d (redirect output to stderr)"
+	depends on BUSYBOX_CONFIG_CROND
+	default BUSYBOX_DEFAULT_FEATURE_CROND_D
+	help
+	-d N sets loglevel (0:most verbose) and directs all output to stderr.
+
+config BUSYBOX_CONFIG_FEATURE_CROND_CALL_SENDMAIL
+	bool "Report command output via email (using sendmail)"
+	default BUSYBOX_DEFAULT_FEATURE_CROND_CALL_SENDMAIL
+	depends on BUSYBOX_CONFIG_CROND
+	help
+	Command output will be sent to corresponding user via email.
+
+config BUSYBOX_CONFIG_FEATURE_CROND_SPECIAL_TIMES
+	bool "Support special times (@reboot, @daily, etc) in crontabs"
+	default BUSYBOX_DEFAULT_FEATURE_CROND_SPECIAL_TIMES
+	depends on BUSYBOX_CONFIG_CROND
+	help
+	string        meaning
+	------        -------
+	@reboot       Run once, at startup
+	@yearly       Run once a year:  "0 0 1 1 *"
+	@annually     Same as @yearly:  "0 0 1 1 *"
+	@monthly      Run once a month: "0 0 1 * *"
+	@weekly       Run once a week:  "0 0 * * 0"
+	@daily        Run once a day:   "0 0 * * *"
+	@midnight     Same as @daily:   "0 0 * * *"
+	@hourly       Run once an hour: "0 * * * *"
+
+config BUSYBOX_CONFIG_FEATURE_CROND_DIR
+	string "crond spool directory"
+	default BUSYBOX_DEFAULT_FEATURE_CROND_DIR
+	depends on BUSYBOX_CONFIG_CROND || BUSYBOX_CONFIG_CRONTAB
+	help
+	Location of crond spool.
+config BUSYBOX_CONFIG_CRONTAB
+	bool "crontab (10 kb)"
+	default BUSYBOX_DEFAULT_CRONTAB
+	help
+	Crontab manipulates the crontab for a particular user. Only
+	the superuser may specify a different user and/or crontab directory.
+	Note that busybox binary must be setuid root for this applet to
+	work properly.
+config BUSYBOX_CONFIG_DEVFSD
+	bool "devfsd (obsolete)"
+	default BUSYBOX_DEFAULT_DEVFSD
+	select BUSYBOX_CONFIG_FEATURE_SYSLOG
+	help
+	This is deprecated and should NOT be used anymore.
+	Use linux >= 2.6 (optionally with hotplug) and mdev instead!
+	See docs/mdev.txt for detailed instructions on how to use mdev
+	instead.
+
+	Provides compatibility with old device names on a devfs systems.
+	You should set it to true if you have devfs enabled.
+	The following keywords in devsfd.conf are supported:
+	"CLEAR_CONFIG", "INCLUDE", "OPTIONAL_INCLUDE", "RESTORE",
+	"PERMISSIONS", "EXECUTE", "COPY", "IGNORE",
+	"MKOLDCOMPAT", "MKNEWCOMPAT","RMOLDCOMPAT", "RMNEWCOMPAT".
+
+	But only if they are written UPPERCASE!!!!!!!!
+
+config BUSYBOX_CONFIG_DEVFSD_MODLOAD
+	bool "Adds support for MODLOAD keyword in devsfd.conf"
+	default BUSYBOX_DEFAULT_DEVFSD_MODLOAD
+	depends on BUSYBOX_CONFIG_DEVFSD
+	help
+	This actually doesn't work with busybox modutils but needs
+	the external modutils.
+
+config BUSYBOX_CONFIG_DEVFSD_FG_NP
+	bool "Enable the -fg and -np options"
+	default BUSYBOX_DEFAULT_DEVFSD_FG_NP
+	depends on BUSYBOX_CONFIG_DEVFSD
+	help
+	-fg  Run the daemon in the foreground.
+	-np  Exit after parsing config. Do not poll for events.
+
+config BUSYBOX_CONFIG_DEVFSD_VERBOSE
+	bool "Increases logging (and size)"
+	default BUSYBOX_DEFAULT_DEVFSD_VERBOSE
+	depends on BUSYBOX_CONFIG_DEVFSD
+	help
+	Increases logging to stderr or syslog.
+
+config BUSYBOX_CONFIG_FEATURE_DEVFS
+	bool "Use devfs names for all devices (obsolete)"
+	default BUSYBOX_DEFAULT_FEATURE_DEVFS
+	help
+	This is obsolete and should NOT be used anymore.
+	Use linux >= 2.6 (optionally with hotplug) and mdev instead!
+
+	For legacy systems -- if there is no way around devfsd -- this
+	tells busybox to look for names like /dev/loop/0 instead of
+	/dev/loop0. If your /dev directory has normal names instead of
+	devfs names, you don't want this.
+config BUSYBOX_CONFIG_DEVMEM
+	bool "devmem (2.5 kb)"
+	default BUSYBOX_DEFAULT_DEVMEM
+	help
+	devmem is a small program that reads and writes from physical
+	memory using /dev/mem.
+config BUSYBOX_CONFIG_FBSPLASH
+	bool "fbsplash (26 kb)"
+	default BUSYBOX_DEFAULT_FBSPLASH
+	help
+	Shows splash image and progress bar on framebuffer device.
+	Can be used during boot phase of an embedded device.
+	Usage:
+	- use kernel option 'vga=xxx' or otherwise enable fb device.
+	- put somewhere fbsplash.cfg file and an image in .ppm format.
+	- $ setsid fbsplash [params] &
+	    -c: hide cursor
+	    -d /dev/fbN: framebuffer device (if not /dev/fb0)
+	    -s path_to_image_file (can be "-" for stdin)
+	    -i path_to_cfg_file (can be "-" for stdin)
+	    -f path_to_fifo (can be "-" for stdin)
+	- if you want to run it only in presence of kernel parameter:
+	    grep -q "fbsplash=on" </proc/cmdline && setsid fbsplash [params] &
+	- commands for fifo:
+	    "NN" (ASCII decimal number) - percentage to show on progress bar
+	    "exit" - well you guessed it
+config BUSYBOX_CONFIG_FLASH_ERASEALL
+	bool "flash_eraseall (5.9 kb)"
+	default BUSYBOX_DEFAULT_FLASH_ERASEALL  # doesn't build on Ubuntu 8.04
+	help
+	The flash_eraseall binary from mtd-utils as of git head c4c6a59eb.
+	This utility is used to erase the whole MTD device.
+config BUSYBOX_CONFIG_FLASH_LOCK
+	bool "flash_lock (2.1 kb)"
+	default BUSYBOX_DEFAULT_FLASH_LOCK  # doesn't build on Ubuntu 8.04
+	help
+	The flash_lock binary from mtd-utils as of git head 5ec0c10d0. This
+	utility locks part or all of the flash device.
+
+config BUSYBOX_CONFIG_FLASH_UNLOCK
+	bool "flash_unlock (1.3 kb)"
+	default BUSYBOX_DEFAULT_FLASH_UNLOCK  # doesn't build on Ubuntu 8.04
+	help
+	The flash_unlock binary from mtd-utils as of git head 5ec0c10d0. This
+	utility unlocks part or all of the flash device.
+config BUSYBOX_CONFIG_FLASHCP
+	bool "flashcp (5.3 kb)"
+	default BUSYBOX_DEFAULT_FLASHCP  # doesn't build on Ubuntu 8.04
+	help
+	The flashcp binary, inspired by mtd-utils as of git head 5eceb74f7.
+	This utility is used to copy images into a MTD device.
+config BUSYBOX_CONFIG_HDPARM
+	bool "hdparm (25 kb)"
+	default BUSYBOX_DEFAULT_HDPARM
+	help
+	Get/Set hard drive parameters. Primarily intended for ATA
+	drives.
+
+config BUSYBOX_CONFIG_FEATURE_HDPARM_GET_IDENTITY
+	bool "Support obtaining detailed information directly from drives"
+	default BUSYBOX_DEFAULT_FEATURE_HDPARM_GET_IDENTITY
+	depends on BUSYBOX_CONFIG_HDPARM
+	help
+	Enable the -I and -i options to obtain detailed information
+	directly from drives about their capabilities and supported ATA
+	feature set. If no device name is specified, hdparm will read
+	identify data from stdin. Enabling this option will add about 16k...
+
+config BUSYBOX_CONFIG_FEATURE_HDPARM_HDIO_SCAN_HWIF
+	bool "Register an IDE interface (DANGEROUS)"
+	default BUSYBOX_DEFAULT_FEATURE_HDPARM_HDIO_SCAN_HWIF
+	depends on BUSYBOX_CONFIG_HDPARM
+	help
+	Enable the 'hdparm -R' option to register an IDE interface.
+	This is dangerous stuff, so you should probably say N.
+
+config BUSYBOX_CONFIG_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF
+	bool "Un-register an IDE interface (DANGEROUS)"
+	default BUSYBOX_DEFAULT_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF
+	depends on BUSYBOX_CONFIG_HDPARM
+	help
+	Enable the 'hdparm -U' option to un-register an IDE interface.
+	This is dangerous stuff, so you should probably say N.
+
+config BUSYBOX_CONFIG_FEATURE_HDPARM_HDIO_DRIVE_RESET
+	bool "Perform device reset (DANGEROUS)"
+	default BUSYBOX_DEFAULT_FEATURE_HDPARM_HDIO_DRIVE_RESET
+	depends on BUSYBOX_CONFIG_HDPARM
+	help
+	Enable the 'hdparm -w' option to perform a device reset.
+	This is dangerous stuff, so you should probably say N.
+
+config BUSYBOX_CONFIG_FEATURE_HDPARM_HDIO_TRISTATE_HWIF
+	bool "Tristate device for hotswap (DANGEROUS)"
+	default BUSYBOX_DEFAULT_FEATURE_HDPARM_HDIO_TRISTATE_HWIF
+	depends on BUSYBOX_CONFIG_HDPARM
+	help
+	Enable the 'hdparm -x' option to tristate device for hotswap,
+	and the '-b' option to get/set bus state. This is dangerous
+	stuff, so you should probably say N.
+
+config BUSYBOX_CONFIG_FEATURE_HDPARM_HDIO_GETSET_DMA
+	bool "Get/set using_dma flag"
+	default BUSYBOX_DEFAULT_FEATURE_HDPARM_HDIO_GETSET_DMA
+	depends on BUSYBOX_CONFIG_HDPARM
+	help
+	Enable the 'hdparm -d' option to get/set using_dma flag.
+config BUSYBOX_CONFIG_HEXEDIT
+	bool "hexedit (21 kb)"
+	default BUSYBOX_DEFAULT_HEXEDIT
+	help
+	Edit file in hexadecimal.
+config BUSYBOX_CONFIG_I2CGET
+	bool "i2cget (5.5 kb)"
+	default BUSYBOX_DEFAULT_I2CGET
+	help
+	Read from I2C/SMBus chip registers.
+
+config BUSYBOX_CONFIG_I2CSET
+	bool "i2cset (6.7 kb)"
+	default BUSYBOX_DEFAULT_I2CSET
+	help
+	Set I2C registers.
+
+config BUSYBOX_CONFIG_I2CDUMP
+	bool "i2cdump (7.1 kb)"
+	default BUSYBOX_DEFAULT_I2CDUMP
+	help
+	Examine I2C registers.
+
+config BUSYBOX_CONFIG_I2CDETECT
+	bool "i2cdetect (7.1 kb)"
+	default BUSYBOX_DEFAULT_I2CDETECT
+	help
+	Detect I2C chips.
+
+config BUSYBOX_CONFIG_I2CTRANSFER
+	bool "i2ctransfer (4.0 kb)"
+	default BUSYBOX_DEFAULT_I2CTRANSFER
+	help
+	Send user-defined I2C messages in one transfer.
+
+config BUSYBOX_CONFIG_INOTIFYD
+	bool "inotifyd (3.6 kb)"
+	default BUSYBOX_DEFAULT_INOTIFYD  # doesn't build on Knoppix 5
+	help
+	Simple inotify daemon. Reports filesystem changes. Requires
+	kernel >= 2.6.13
+config BUSYBOX_CONFIG_LESS
+	bool "less (16 kb)"
+	default BUSYBOX_DEFAULT_LESS
+	help
+	'less' is a pager, meaning that it displays text files. It possesses
+	a wide array of features, and is an improvement over 'more'.
+
+config BUSYBOX_CONFIG_FEATURE_LESS_MAXLINES
+	int "Max number of input lines less will try to eat"
+	default BUSYBOX_DEFAULT_FEATURE_LESS_MAXLINES
+	depends on BUSYBOX_CONFIG_LESS
+
+config BUSYBOX_CONFIG_FEATURE_LESS_BRACKETS
+	bool "Enable bracket searching"
+	default BUSYBOX_DEFAULT_FEATURE_LESS_BRACKETS
+	depends on BUSYBOX_CONFIG_LESS
+	help
+	This option adds the capability to search for matching left and right
+	brackets, facilitating programming.
+
+config BUSYBOX_CONFIG_FEATURE_LESS_FLAGS
+	bool "Enable -m/-M"
+	default BUSYBOX_DEFAULT_FEATURE_LESS_FLAGS
+	depends on BUSYBOX_CONFIG_LESS
+	help
+	The -M/-m flag enables a more sophisticated status line.
+
+config BUSYBOX_CONFIG_FEATURE_LESS_TRUNCATE
+	bool "Enable -S"
+	default BUSYBOX_DEFAULT_FEATURE_LESS_TRUNCATE
+	depends on BUSYBOX_CONFIG_LESS
+	help
+	The -S flag causes long lines to be truncated rather than
+	wrapped.
+
+config BUSYBOX_CONFIG_FEATURE_LESS_MARKS
+	bool "Enable marks"
+	default BUSYBOX_DEFAULT_FEATURE_LESS_MARKS
+	depends on BUSYBOX_CONFIG_LESS
+	help
+	Marks enable positions in a file to be stored for easy reference.
+
+config BUSYBOX_CONFIG_FEATURE_LESS_REGEXP
+	bool "Enable regular expressions"
+	default BUSYBOX_DEFAULT_FEATURE_LESS_REGEXP
+	depends on BUSYBOX_CONFIG_LESS
+	help
+	Enable regular expressions, allowing complex file searches.
+
+config BUSYBOX_CONFIG_FEATURE_LESS_WINCH
+	bool "Enable automatic resizing on window size changes"
+	default BUSYBOX_DEFAULT_FEATURE_LESS_WINCH
+	depends on BUSYBOX_CONFIG_LESS
+	help
+	Makes less track window size changes.
+
+config BUSYBOX_CONFIG_FEATURE_LESS_ASK_TERMINAL
+	bool "Use 'tell me cursor position' ESC sequence to measure window"
+	default BUSYBOX_DEFAULT_FEATURE_LESS_ASK_TERMINAL
+	depends on BUSYBOX_CONFIG_FEATURE_LESS_WINCH
+	help
+	Makes less track window size changes.
+	If terminal size can't be retrieved and $LINES/$COLUMNS are not set,
+	this option makes less perform a last-ditch effort to find it:
+	position cursor to 999,999 and ask terminal to report real
+	cursor position using "ESC [ 6 n" escape sequence, then read stdin.
+	This is not clean but helps a lot on serial lines and such.
+
+config BUSYBOX_CONFIG_FEATURE_LESS_DASHCMD
+	bool "Enable flag changes ('-' command)"
+	default BUSYBOX_DEFAULT_FEATURE_LESS_DASHCMD
+	depends on BUSYBOX_CONFIG_LESS
+	help
+	This enables the ability to change command-line flags within
+	less itself ('-' keyboard command).
+
+config BUSYBOX_CONFIG_FEATURE_LESS_LINENUMS
+	bool "Enable -N (dynamic switching of line numbers)"
+	default BUSYBOX_DEFAULT_FEATURE_LESS_LINENUMS
+	depends on BUSYBOX_CONFIG_FEATURE_LESS_DASHCMD
+
+config BUSYBOX_CONFIG_FEATURE_LESS_RAW
+	bool "Enable -R ('raw control characters')"
+	default BUSYBOX_DEFAULT_FEATURE_LESS_RAW
+	depends on BUSYBOX_CONFIG_FEATURE_LESS_DASHCMD
+	help
+	This is essential for less applet to work with tools that use colors
+	and paging, such as git, systemd tools or nmcli.
+
+config BUSYBOX_CONFIG_FEATURE_LESS_ENV
+	bool "Take options from $LESS environment variable"
+	default BUSYBOX_DEFAULT_FEATURE_LESS_ENV
+	depends on BUSYBOX_CONFIG_FEATURE_LESS_DASHCMD
+	help
+	This is essential for less applet to work with tools that use colors
+	and paging, such as git, systemd tools or nmcli.
+config BUSYBOX_CONFIG_LOCK
+	bool "lock"
+	default BUSYBOX_DEFAULT_LOCK
+	help
+	  Small utility for using locks in scripts
+config BUSYBOX_CONFIG_LSSCSI
+	bool "lsscsi (2.5 kb)"
+	default BUSYBOX_DEFAULT_LSSCSI
+	help
+	lsscsi is a utility for displaying information about SCSI buses in the
+	system and devices connected to them.
+
+	This version uses sysfs (/sys/bus/scsi/devices) only.
+config BUSYBOX_CONFIG_MAKEDEVS
+	bool "makedevs (9.2 kb)"
+	default BUSYBOX_DEFAULT_MAKEDEVS
+	help
+	'makedevs' is a utility used to create a batch of devices with
+	one command.
+
+	There are two choices for command line behaviour, the interface
+	as used by LEAF/Linux Router Project, or a device table file.
+
+	'leaf' is traditionally what busybox follows, it allows multiple
+	devices of a particluar type to be created per command.
+	e.g. /dev/hda[0-9]
+	Device properties are passed as command line arguments.
+
+	'table' reads device properties from a file or stdin, allowing
+	a batch of unrelated devices to be made with one command.
+	User/group names are allowed as an alternative to uid/gid.
+
+choice
+	prompt "Choose makedevs behaviour"
+	depends on BUSYBOX_CONFIG_MAKEDEVS
+	default BUSYBOX_CONFIG_FEATURE_MAKEDEVS_TABLE
+
+config BUSYBOX_CONFIG_FEATURE_MAKEDEVS_LEAF
+	bool "leaf"
+
+config BUSYBOX_CONFIG_FEATURE_MAKEDEVS_TABLE
+	bool "table"
+
+endchoice
+config BUSYBOX_CONFIG_MAN
+	bool "man (26 kb)"
+	default BUSYBOX_DEFAULT_MAN
+	help
+	Format and display manual pages.
+config BUSYBOX_CONFIG_MICROCOM
+	bool "microcom (5.7 kb)"
+	default BUSYBOX_DEFAULT_MICROCOM
+	help
+	The poor man's minicom utility for chatting with serial port devices.
+config BUSYBOX_CONFIG_MIM
+	bool "mim (0.5 kb)"
+	default BUSYBOX_DEFAULT_MIM
+	depends on BUSYBOX_CONFIG_FEATURE_SH_EMBEDDED_SCRIPTS
+	help
+	Run a script from a Makefile-like specification file.
+	Unlike 'make' dependencies aren't supported.
+config BUSYBOX_CONFIG_MT
+	bool "mt (2.5 kb)"
+	default BUSYBOX_DEFAULT_MT
+	help
+	mt is used to control tape devices. You can use the mt utility
+	to advance or rewind a tape past a specified number of archive
+	files on the tape.
+config BUSYBOX_CONFIG_NANDWRITE
+	bool "nandwrite (4.8 kb)"
+	default BUSYBOX_DEFAULT_NANDWRITE
+	help
+	Write to the specified MTD device, with bad blocks awareness
+
+config BUSYBOX_CONFIG_NANDDUMP
+	bool "nanddump (5.2 kb)"
+	default BUSYBOX_DEFAULT_NANDDUMP
+	help
+	Dump the content of raw NAND chip
+config BUSYBOX_CONFIG_PARTPROBE
+	bool "partprobe (3.5 kb)"
+	default BUSYBOX_DEFAULT_PARTPROBE
+	help
+	Ask kernel to rescan partition table.
+config BUSYBOX_CONFIG_RAIDAUTORUN
+	bool "raidautorun (1.3 kb)"
+	default BUSYBOX_DEFAULT_RAIDAUTORUN
+	help
+	raidautorun tells the kernel md driver to
+	search and start RAID arrays.
+config BUSYBOX_CONFIG_READAHEAD
+	bool "readahead (1.5 kb)"
+	default BUSYBOX_DEFAULT_READAHEAD
+	depends on BUSYBOX_CONFIG_LFS
+	help
+	Preload the files listed on the command line into RAM cache so that
+	subsequent reads on these files will not block on disk I/O.
+
+	This applet just calls the readahead(2) system call on each file.
+	It is mainly useful in system startup scripts to preload files
+	or executables before they are used. When used at the right time
+	(in particular when a CPU bound process is running) it can
+	significantly speed up system startup.
+
+	As readahead(2) blocks until each file has been read, it is best to
+	run this applet as a background job.
+config BUSYBOX_CONFIG_RFKILL
+	bool "rfkill (4.4 kb)"
+	default BUSYBOX_DEFAULT_RFKILL # doesn't build on Ubuntu 9.04
+	help
+	Enable/disable wireless devices.
+
+	rfkill list : list all wireless devices
+	rfkill list bluetooth : list all bluetooth devices
+	rfkill list 1 : list device corresponding to the given index
+	rfkill block|unblock wlan : block/unblock all wlan(wifi) devices
+
+config BUSYBOX_CONFIG_RUNLEVEL
+	bool "runlevel (559 bytes)"
+	default BUSYBOX_DEFAULT_RUNLEVEL
+	depends on BUSYBOX_CONFIG_FEATURE_UTMP
+	help
+	Find the current and previous system runlevel.
+
+	This applet uses utmp but does not rely on busybox supporing
+	utmp on purpose. It is used by e.g. emdebian via /etc/init.d/rc.
+config BUSYBOX_CONFIG_RX
+	bool "rx (2.9 kb)"
+	default BUSYBOX_DEFAULT_RX
+	help
+	Receive files using the Xmodem protocol.
+config BUSYBOX_CONFIG_SEEDRNG
+	bool "seedrng (1.3 kb)"
+	default BUSYBOX_DEFAULT_SEEDRNG
+	help
+	Seed the kernel RNG from seed files, meant to be called
+	once during startup, once during shutdown, and optionally
+	at some periodic interval in between.
+config BUSYBOX_CONFIG_SETFATTR
+	bool "setfattr (3.7 kb)"
+	default BUSYBOX_DEFAULT_SETFATTR
+	help
+	Set/delete extended attributes on files
+config BUSYBOX_CONFIG_SETSERIAL
+	bool "setserial (6.9 kb)"
+	default BUSYBOX_DEFAULT_SETSERIAL
+	help
+	Retrieve or set Linux serial port.
+config BUSYBOX_CONFIG_STRINGS
+	bool "strings (4.6 kb)"
+	default BUSYBOX_DEFAULT_STRINGS
+	help
+	strings prints the printable character sequences for each file
+	specified.
+config BUSYBOX_CONFIG_TIME
+	bool "time (6.8 kb)"
+	default BUSYBOX_DEFAULT_TIME
+	help
+	The time command runs the specified program with the given arguments.
+	When the command finishes, time writes a message to standard output
+	giving timing statistics about this program run.
+config BUSYBOX_CONFIG_TREE
+	bool "tree (0.6 kb)"
+	default BUSYBOX_DEFAULT_TREE
+	help
+	List files and directories in a tree structure.
+config BUSYBOX_CONFIG_TS
+	bool "ts (450 bytes)"
+	default BUSYBOX_DEFAULT_TS
+config BUSYBOX_CONFIG_TTYSIZE
+	bool "ttysize (432 bytes)"
+	default BUSYBOX_DEFAULT_TTYSIZE
+	help
+	A replacement for "stty size". Unlike stty, can report only width,
+	only height, or both, in any order. It also does not complain on
+	error, but returns default 80x24.
+	Usage in shell scripts: width=`ttysize w`.
+config BUSYBOX_CONFIG_UBIATTACH
+	bool "ubiattach (4.2 kb)"
+	default BUSYBOX_DEFAULT_UBIATTACH
+	help
+	Attach MTD device to an UBI device.
+
+config BUSYBOX_CONFIG_UBIDETACH
+	bool "ubidetach (4.1 kb)"
+	default BUSYBOX_DEFAULT_UBIDETACH
+	help
+	Detach MTD device from an UBI device.
+
+config BUSYBOX_CONFIG_UBIMKVOL
+	bool "ubimkvol (5.3 kb)"
+	default BUSYBOX_DEFAULT_UBIMKVOL
+	help
+	Create a UBI volume.
+
+config BUSYBOX_CONFIG_UBIRMVOL
+	bool "ubirmvol (4.9 kb)"
+	default BUSYBOX_DEFAULT_UBIRMVOL
+	help
+	Delete a UBI volume.
+
+config BUSYBOX_CONFIG_UBIRSVOL
+	bool "ubirsvol (4.2 kb)"
+	default BUSYBOX_DEFAULT_UBIRSVOL
+	help
+	Resize a UBI volume.
+
+config BUSYBOX_CONFIG_UBIUPDATEVOL
+	bool "ubiupdatevol (5.2 kb)"
+	default BUSYBOX_DEFAULT_UBIUPDATEVOL
+	help
+	Update a UBI volume.
+config BUSYBOX_CONFIG_UBIRENAME
+	bool "ubirename (2.4 kb)"
+	default BUSYBOX_DEFAULT_UBIRENAME
+	help
+	Utility to rename UBI volumes
+config BUSYBOX_CONFIG_VOLNAME
+	bool "volname (1.6 kb)"
+	default BUSYBOX_DEFAULT_VOLNAME
+	help
+	Prints a CD-ROM volume name.
+config BUSYBOX_CONFIG_WATCHDOG
+	bool "watchdog (5.3 kb)"
+	default BUSYBOX_DEFAULT_WATCHDOG
+	help
+	The watchdog utility is used with hardware or software watchdog
+	device drivers. It opens the specified watchdog device special file
+	and periodically writes a magic character to the device. If the
+	watchdog applet ever fails to write the magic character within a
+	certain amount of time, the watchdog device assumes the system has
+	hung, and will cause the hardware to reboot.
+
+config BUSYBOX_CONFIG_FEATURE_WATCHDOG_OPEN_TWICE
+	bool "Open watchdog device twice, closing it gracefully in between"
+	depends on BUSYBOX_CONFIG_WATCHDOG
+	default BUSYBOX_DEFAULT_FEATURE_WATCHDOG_OPEN_TWICE   # this behavior was essentially a hack for a broken driver
+	help
+	When enabled, the watchdog device is opened and then immediately
+	magic-closed, before being opened a second time. This may be necessary
+	for some watchdog devices, but can cause spurious warnings in the
+	kernel log if the nowayout feature is enabled. If this workaround
+	is really needed for you machine to work properly, consider whether
+	it should be fixed in the kernel driver instead. Even when disabled,
+	the behaviour is easily emulated with a "printf 'V' > /dev/watchdog"
+	immediately before starting the busybox watchdog daemon. Say n unless
+	you know that you absolutely need this.
+
+endmenu
diff --git a/package/utils/busybox/config/modutils/Config.in b/package/utils/busybox/config/modutils/Config.in
new file mode 100644
index 0000000..e353808
--- /dev/null
+++ b/package/utils/busybox/config/modutils/Config.in
@@ -0,0 +1,239 @@
+# DO NOT EDIT. This file is generated from Config.src
+#
+# For a description of the syntax of this configuration file,
+# see docs/Kconfig-language.txt.
+#
+
+menu "Linux Module Utilities"
+
+config BUSYBOX_CONFIG_MODPROBE_SMALL
+	bool "Simplified modutils"
+	default BUSYBOX_DEFAULT_MODPROBE_SMALL
+	help
+	Build smaller (~1.5 kbytes), simplified module tools.
+
+	This option by itself does not enable any applets -
+	you need to select applets individually below.
+
+	With this option modprobe does not require modules.dep file
+	and does not use /etc/modules.conf file.
+	It scans module files in /lib/modules/`uname -r` and
+	determines dependencies and module alias names on the fly.
+	This may make module loading slower, most notably
+	when one needs to load module by alias (this requires
+	scanning through module _bodies_).
+
+	At the first attempt to load a module by alias modprobe
+	will try to generate modules.dep.bb file in order to speed up
+	future loads by alias. Failure to do so (read-only /lib/modules,
+	etc) is not reported, and future modprobes will be slow too.
+
+	NB: modules.dep.bb file format is not compatible
+	with modules.dep file as created/used by standard module tools.
+
+	Additional module parameters can be stored in
+	/etc/modules/$module_name files.
+
+config BUSYBOX_CONFIG_DEPMOD
+	bool "depmod (27 kb)"
+	default BUSYBOX_DEFAULT_DEPMOD
+	help
+	depmod generates modules.dep (and potentially modules.alias
+	and modules.symbols) that contain dependency information
+	for modprobe.
+config BUSYBOX_CONFIG_INSMOD
+	bool "insmod (22 kb)"
+	default BUSYBOX_DEFAULT_INSMOD
+	help
+	insmod is used to load specified modules in the running kernel.
+config BUSYBOX_CONFIG_LSMOD
+	bool "lsmod (1.9 kb)"
+	default BUSYBOX_DEFAULT_LSMOD
+	help
+	lsmod is used to display a list of loaded modules.
+
+config BUSYBOX_CONFIG_FEATURE_LSMOD_PRETTY_2_6_OUTPUT
+	bool "Pretty output"
+	default BUSYBOX_DEFAULT_FEATURE_LSMOD_PRETTY_2_6_OUTPUT
+	depends on BUSYBOX_CONFIG_LSMOD && !BUSYBOX_CONFIG_MODPROBE_SMALL
+	help
+	This option makes output format of lsmod adjusted to
+	the format of module-init-tools for Linux kernel 2.6.
+	Increases size somewhat.
+config BUSYBOX_CONFIG_MODINFO
+	bool "modinfo (24 kb)"
+	default BUSYBOX_DEFAULT_MODINFO
+	help
+	Show information about a Linux Kernel module
+config BUSYBOX_CONFIG_MODPROBE
+	bool "modprobe (28 kb)"
+	default BUSYBOX_DEFAULT_MODPROBE
+	help
+	Handle the loading of modules, and their dependencies on a high
+	level.
+
+config BUSYBOX_CONFIG_FEATURE_MODPROBE_BLACKLIST
+	bool "Blacklist support"
+	default BUSYBOX_DEFAULT_FEATURE_MODPROBE_BLACKLIST
+	depends on BUSYBOX_CONFIG_MODPROBE && !BUSYBOX_CONFIG_MODPROBE_SMALL
+	help
+	Say 'y' here to enable support for the 'blacklist' command in
+	modprobe.conf. This prevents the alias resolver to resolve
+	blacklisted modules. This is useful if you want to prevent your
+	hardware autodetection scripts to load modules like evdev, frame
+	buffer drivers etc.
+config BUSYBOX_CONFIG_RMMOD
+	bool "rmmod (3.3 kb)"
+	default BUSYBOX_DEFAULT_RMMOD
+	help
+	rmmod is used to unload specified modules from the kernel.
+
+comment "Options common to multiple modutils"
+
+config BUSYBOX_CONFIG_FEATURE_CMDLINE_MODULE_OPTIONS
+	bool "Accept module options on modprobe command line"
+	default BUSYBOX_DEFAULT_FEATURE_CMDLINE_MODULE_OPTIONS
+	depends on BUSYBOX_CONFIG_INSMOD || BUSYBOX_CONFIG_MODPROBE
+	help
+	Allow insmod and modprobe take module options from the applets'
+	command line.
+
+config BUSYBOX_CONFIG_FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED
+	bool "Skip loading of already loaded modules"
+	default BUSYBOX_DEFAULT_FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED
+	depends on BUSYBOX_CONFIG_MODPROBE_SMALL && (BUSYBOX_CONFIG_DEPMOD || BUSYBOX_CONFIG_INSMOD || BUSYBOX_CONFIG_MODPROBE)
+	help
+	Check if the module is already loaded.
+
+config BUSYBOX_CONFIG_FEATURE_2_4_MODULES
+	bool "Support version 2.2/2.4 Linux kernels"
+	default BUSYBOX_DEFAULT_FEATURE_2_4_MODULES
+	depends on (BUSYBOX_CONFIG_INSMOD || BUSYBOX_CONFIG_LSMOD || BUSYBOX_CONFIG_MODPROBE || BUSYBOX_CONFIG_RMMOD) && !BUSYBOX_CONFIG_MODPROBE_SMALL
+	help
+	Support module loading for 2.2.x and 2.4.x Linux kernels.
+	This increases size considerably. Say N unless you plan
+	to run ancient kernels.
+
+config BUSYBOX_CONFIG_FEATURE_INSMOD_VERSION_CHECKING
+	bool "Enable module version checking"
+	default BUSYBOX_DEFAULT_FEATURE_INSMOD_VERSION_CHECKING
+	depends on BUSYBOX_CONFIG_FEATURE_2_4_MODULES && (BUSYBOX_CONFIG_INSMOD || BUSYBOX_CONFIG_MODPROBE)
+	help
+	Support checking of versions for modules. This is used to
+	ensure that the kernel and module are made for each other.
+
+config BUSYBOX_CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
+	bool "Add module symbols to kernel symbol table"
+	default BUSYBOX_DEFAULT_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
+	depends on BUSYBOX_CONFIG_FEATURE_2_4_MODULES && (BUSYBOX_CONFIG_INSMOD || BUSYBOX_CONFIG_MODPROBE)
+	help
+	By adding module symbols to the kernel symbol table, Oops messages
+	occurring within kernel modules can be properly debugged. By enabling
+	this feature, module symbols will always be added to the kernel symbol
+	table for proper debugging support. If you are not interested in
+	Oops messages from kernel modules, say N.
+
+config BUSYBOX_CONFIG_FEATURE_INSMOD_LOADINKMEM
+	bool "In kernel memory optimization (uClinux only)"
+	default BUSYBOX_DEFAULT_FEATURE_INSMOD_LOADINKMEM
+	depends on BUSYBOX_CONFIG_FEATURE_2_4_MODULES && (BUSYBOX_CONFIG_INSMOD || BUSYBOX_CONFIG_MODPROBE)
+	help
+	This is a special uClinux only memory optimization that lets insmod
+	load the specified kernel module directly into kernel space, reducing
+	memory usage by preventing the need for two copies of the module
+	being loaded into memory.
+
+config BUSYBOX_CONFIG_FEATURE_INSMOD_LOAD_MAP
+	bool "Enable insmod load map (-m) option"
+	default BUSYBOX_DEFAULT_FEATURE_INSMOD_LOAD_MAP
+	depends on BUSYBOX_CONFIG_FEATURE_2_4_MODULES && BUSYBOX_CONFIG_INSMOD
+	help
+	Enabling this, one would be able to get a load map
+	output on stdout. This makes kernel module debugging
+	easier.
+	If you don't plan to debug kernel modules, you
+	don't need this option.
+
+config BUSYBOX_CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL
+	bool "Symbols in load map"
+	default BUSYBOX_DEFAULT_FEATURE_INSMOD_LOAD_MAP_FULL
+	depends on BUSYBOX_CONFIG_FEATURE_INSMOD_LOAD_MAP
+	help
+	Without this option, -m will only output section
+	load map. With this option, -m will also output
+	symbols load map.
+
+config BUSYBOX_CONFIG_FEATURE_CHECK_TAINTED_MODULE
+	bool "Support tainted module checking with new kernels"
+	default BUSYBOX_DEFAULT_FEATURE_CHECK_TAINTED_MODULE
+	depends on (BUSYBOX_CONFIG_LSMOD || BUSYBOX_CONFIG_FEATURE_2_4_MODULES) && !BUSYBOX_CONFIG_MODPROBE_SMALL
+	help
+	Support checking for tainted modules. These are usually binary
+	only modules that will make the linux-kernel list ignore your
+	support request.
+	This option is required to support GPLONLY modules.
+
+config BUSYBOX_CONFIG_FEATURE_INSMOD_TRY_MMAP
+	bool "Try to load module from a mmap'ed area"
+	default BUSYBOX_DEFAULT_FEATURE_INSMOD_TRY_MMAP
+	depends on (BUSYBOX_CONFIG_INSMOD || BUSYBOX_CONFIG_MODPROBE) && !BUSYBOX_CONFIG_MODPROBE_SMALL
+	help
+	This option causes module loading code to try to mmap
+	module first. If it does not work (for example,
+	it does not work for compressed modules), module will be read
+	(and unpacked if needed) into a memory block allocated by malloc.
+
+	The only case when mmap works but malloc does not is when
+	you are trying to load a big module on a very memory-constrained
+	machine. Malloc will momentarily need 2x as much memory as mmap.
+
+	Choosing N saves about 250 bytes of code (on 32-bit x86).
+
+config BUSYBOX_CONFIG_FEATURE_MODUTILS_ALIAS
+	bool "Support module.aliases file"
+	default BUSYBOX_DEFAULT_FEATURE_MODUTILS_ALIAS
+	depends on (BUSYBOX_CONFIG_DEPMOD || BUSYBOX_CONFIG_MODPROBE) && !BUSYBOX_CONFIG_MODPROBE_SMALL
+	help
+	Generate and parse modules.alias containing aliases for bus
+	identifiers:
+		alias pcmcia:m*c*f03fn*pfn*pa*pb*pc*pd* parport_cs
+
+	and aliases for logical modules names e.g.:
+		alias padlock_aes aes
+		alias aes_i586 aes
+		alias aes_generic aes
+
+	Say Y if unsure.
+
+config BUSYBOX_CONFIG_FEATURE_MODUTILS_SYMBOLS
+	bool "Support module.symbols file"
+	default BUSYBOX_DEFAULT_FEATURE_MODUTILS_SYMBOLS
+	depends on (BUSYBOX_CONFIG_DEPMOD || BUSYBOX_CONFIG_MODPROBE) && !BUSYBOX_CONFIG_MODPROBE_SMALL
+	help
+	Generate and parse modules.symbols containing aliases for
+	symbol_request() kernel calls, such as:
+		alias symbol:usb_sg_init usbcore
+
+	Say Y if unsure.
+
+config BUSYBOX_CONFIG_DEFAULT_MODULES_DIR
+	string "Default directory containing modules"
+	default BUSYBOX_DEFAULT_DEFAULT_MODULES_DIR
+	depends on BUSYBOX_CONFIG_DEPMOD || BUSYBOX_CONFIG_MODPROBE || BUSYBOX_CONFIG_MODINFO
+	help
+	Directory that contains kernel modules.
+	Defaults to "/lib/modules"
+
+config BUSYBOX_CONFIG_DEFAULT_DEPMOD_FILE
+	string "Default name of modules.dep"
+	default BUSYBOX_DEFAULT_DEFAULT_DEPMOD_FILE
+	depends on BUSYBOX_CONFIG_DEPMOD || BUSYBOX_CONFIG_MODPROBE || BUSYBOX_CONFIG_MODINFO
+	help
+	Filename that contains kernel modules dependencies.
+	Defaults to "modules.dep".
+	If you configured the "simplified modutils" (MODPROBE_SMALL), a
+	".bb" suffix will be added after this name. Do not specify ".bb"
+	here unless you intend your depmod or modprobe to work on
+	"modules.dep.bb.bb" or such.
+
+endmenu
diff --git a/package/utils/busybox/config/networking/Config.in b/package/utils/busybox/config/networking/Config.in
new file mode 100644
index 0000000..861e4f9
--- /dev/null
+++ b/package/utils/busybox/config/networking/Config.in
@@ -0,0 +1,1263 @@
+# DO NOT EDIT. This file is generated from Config.src
+#
+# For a description of the syntax of this configuration file,
+# see docs/Kconfig-language.txt.
+#
+
+menu "Networking Utilities"
+
+config BUSYBOX_CONFIG_FEATURE_IPV6
+	bool "Enable IPv6 support"
+	default BUSYBOX_DEFAULT_FEATURE_IPV6
+	help
+	Enable IPv6 support in busybox.
+	This adds IPv6 support in the networking applets.
+
+config BUSYBOX_CONFIG_FEATURE_UNIX_LOCAL
+	bool "Enable Unix domain socket support (usually not needed)"
+	default BUSYBOX_DEFAULT_FEATURE_UNIX_LOCAL
+	help
+	Enable Unix domain socket support in all busybox networking
+	applets.  Address of the form local:/path/to/unix/socket
+	will be recognized.
+
+	This extension is almost never used in real world usage.
+	You most likely want to say N.
+
+config BUSYBOX_CONFIG_FEATURE_PREFER_IPV4_ADDRESS
+	bool "Prefer IPv4 addresses from DNS queries"
+	default BUSYBOX_DEFAULT_FEATURE_PREFER_IPV4_ADDRESS
+	depends on BUSYBOX_CONFIG_FEATURE_IPV6
+	help
+	Use IPv4 address of network host if it has one.
+
+	If this option is off, the first returned address will be used.
+	This may cause problems when your DNS server is IPv6-capable and
+	is returning IPv6 host addresses too. If IPv6 address
+	precedes IPv4 one in DNS reply, busybox network applets
+	(e.g. wget) will use IPv6 address. On an IPv6-incapable host
+	or network applets will fail to connect to the host
+	using IPv6 address.
+
+config BUSYBOX_CONFIG_VERBOSE_RESOLUTION_ERRORS
+	bool "Verbose resolution errors"
+	default BUSYBOX_DEFAULT_VERBOSE_RESOLUTION_ERRORS
+	help
+	Enable if you are not satisfied with simplistic
+	"can't resolve 'hostname.com'" and want to know more.
+	This may increase size of your executable a bit.
+
+config BUSYBOX_CONFIG_FEATURE_ETC_NETWORKS
+	bool "Support /etc/networks"
+	default BUSYBOX_DEFAULT_FEATURE_ETC_NETWORKS
+	help
+	Enable support for network names in /etc/networks. This is
+	a rarely used feature which allows you to use names
+	instead of IP/mask pairs in route command.
+
+config BUSYBOX_CONFIG_FEATURE_ETC_SERVICES
+	bool "Consult /etc/services even for well-known ports"
+	default BUSYBOX_DEFAULT_FEATURE_ETC_SERVICES
+	help
+	Look up e.g. "telnet" and "http" in /etc/services file
+	instead of assuming ports 23 and 80.
+	This is almost never necessary (everybody uses standard ports),
+	and it makes sense to avoid reading this file.
+	If you disable this option, in the cases where port is explicitly
+	specified as a service name (e.g. "telnet HOST PORTNAME"),
+	it will still be looked up in /etc/services.
+
+config BUSYBOX_CONFIG_FEATURE_HWIB
+	bool "Support infiniband HW"
+	default BUSYBOX_DEFAULT_FEATURE_HWIB
+	help
+	Support for printing infiniband addresses in network applets.
+
+config BUSYBOX_CONFIG_FEATURE_TLS_SHA1
+	bool "In TLS code, support ciphers which use deprecated SHA1"
+	depends on BUSYBOX_CONFIG_TLS
+	default BUSYBOX_DEFAULT_FEATURE_TLS_SHA1
+	help
+	Selecting this option increases interoperability with very old
+	servers, but slightly increases code size.
+
+	Most TLS servers support SHA256 today (2018), since SHA1 is
+	considered possibly insecure (although not yet definitely broken).
+
+config BUSYBOX_CONFIG_ARP
+	bool "arp (10 kb)"
+	default BUSYBOX_DEFAULT_ARP
+	help
+	Manipulate the system ARP cache.
+config BUSYBOX_CONFIG_ARPING
+	bool "arping (9 kb)"
+	default BUSYBOX_DEFAULT_ARPING
+	help
+	Ping hosts by ARP packets.
+config BUSYBOX_CONFIG_BRCTL
+	bool "brctl (4.7 kb)"
+	default BUSYBOX_DEFAULT_BRCTL
+	help
+	Manage ethernet bridges.
+	Supports addbr/delbr and addif/delif.
+
+config BUSYBOX_CONFIG_FEATURE_BRCTL_FANCY
+	bool "Fancy options"
+	default BUSYBOX_DEFAULT_FEATURE_BRCTL_FANCY
+	depends on BUSYBOX_CONFIG_BRCTL
+	help
+	Add support for extended option like:
+		setageing, setfd, sethello, setmaxage,
+		setpathcost, setportprio, setbridgeprio,
+		stp
+	This adds about 600 bytes.
+
+config BUSYBOX_CONFIG_FEATURE_BRCTL_SHOW
+	bool "Support show"
+	default BUSYBOX_DEFAULT_FEATURE_BRCTL_SHOW
+	depends on BUSYBOX_CONFIG_BRCTL && BUSYBOX_CONFIG_FEATURE_BRCTL_FANCY
+	help
+	Add support for option which prints the current config:
+		show
+config BUSYBOX_CONFIG_DNSD
+	bool "dnsd (9.8 kb)"
+	default BUSYBOX_DEFAULT_DNSD
+	help
+	Small and static DNS server daemon.
+config BUSYBOX_CONFIG_ETHER_WAKE
+	bool "ether-wake (4.9 kb)"
+	default BUSYBOX_DEFAULT_ETHER_WAKE
+	help
+	Send a magic packet to wake up sleeping machines.
+config BUSYBOX_CONFIG_FTPD
+	bool "ftpd (30 kb)"
+	default BUSYBOX_DEFAULT_FTPD
+	help
+	Simple FTP daemon. You have to run it via inetd.
+
+config BUSYBOX_CONFIG_FEATURE_FTPD_WRITE
+	bool "Enable -w (upload commands)"
+	default BUSYBOX_DEFAULT_FEATURE_FTPD_WRITE
+	depends on BUSYBOX_CONFIG_FTPD
+	help
+	Enable -w option. "ftpd -w" will accept upload commands
+	such as STOR, STOU, APPE, DELE, MKD, RMD, rename commands.
+
+config BUSYBOX_CONFIG_FEATURE_FTPD_ACCEPT_BROKEN_LIST
+	bool "Enable workaround for RFC-violating clients"
+	default BUSYBOX_DEFAULT_FEATURE_FTPD_ACCEPT_BROKEN_LIST
+	depends on BUSYBOX_CONFIG_FTPD
+	help
+	Some ftp clients (among them KDE's Konqueror) issue illegal
+	"LIST -l" requests. This option works around such problems.
+	It might prevent you from listing files starting with "-" and
+	it increases the code size by ~40 bytes.
+	Most other ftp servers seem to behave similar to this.
+
+config BUSYBOX_CONFIG_FEATURE_FTPD_AUTHENTICATION
+	bool "Enable authentication"
+	default BUSYBOX_DEFAULT_FEATURE_FTPD_AUTHENTICATION
+	depends on BUSYBOX_CONFIG_FTPD
+	help
+	Require login, and change to logged in user's UID:GID before
+	accessing any files. Option "-a USER" allows "anonymous"
+	logins (treats them as if USER logged in).
+
+	If this option is not selected, ftpd runs with the rights
+	of the user it was started under, and does not require login.
+	Take care to not launch it under root.
+config BUSYBOX_CONFIG_FTPGET
+	bool "ftpget (7.8 kb)"
+	default BUSYBOX_DEFAULT_FTPGET
+	help
+	Retrieve a remote file via FTP.
+
+config BUSYBOX_CONFIG_FTPPUT
+	bool "ftpput (7.5 kb)"
+	default BUSYBOX_DEFAULT_FTPPUT
+	help
+	Store a remote file via FTP.
+
+config BUSYBOX_CONFIG_FEATURE_FTPGETPUT_LONG_OPTIONS
+	bool "Enable long options in ftpget/ftpput"
+	default BUSYBOX_DEFAULT_FEATURE_FTPGETPUT_LONG_OPTIONS
+	depends on BUSYBOX_CONFIG_LONG_OPTS && (BUSYBOX_CONFIG_FTPGET || BUSYBOX_CONFIG_FTPPUT)
+config BUSYBOX_CONFIG_HOSTNAME
+	bool "hostname (5.5 kb)"
+	default BUSYBOX_DEFAULT_HOSTNAME
+	help
+	Show or set the system's host name.
+
+config BUSYBOX_CONFIG_DNSDOMAINNAME
+	bool "dnsdomainname (3.6 kb)"
+	default BUSYBOX_DEFAULT_DNSDOMAINNAME
+	help
+	Alias to "hostname -d".
+config BUSYBOX_CONFIG_HTTPD
+	bool "httpd (32 kb)"
+	default BUSYBOX_DEFAULT_HTTPD
+	help
+	HTTP server.
+
+config BUSYBOX_CONFIG_FEATURE_HTTPD_PORT_DEFAULT
+	int "Default port"
+	default BUSYBOX_DEFAULT_FEATURE_HTTPD_PORT_DEFAULT
+	range 1 65535
+	depends on BUSYBOX_CONFIG_HTTPD
+
+config BUSYBOX_CONFIG_FEATURE_HTTPD_RANGES
+	bool "Support 'Ranges:' header"
+	default BUSYBOX_DEFAULT_FEATURE_HTTPD_RANGES
+	depends on BUSYBOX_CONFIG_HTTPD
+	help
+	Makes httpd emit "Accept-Ranges: bytes" header and understand
+	"Range: bytes=NNN-[MMM]" header. Allows for resuming interrupted
+	downloads, seeking in multimedia players etc.
+
+config BUSYBOX_CONFIG_FEATURE_HTTPD_SETUID
+	bool "Enable -u <user> option"
+	default BUSYBOX_DEFAULT_FEATURE_HTTPD_SETUID
+	depends on BUSYBOX_CONFIG_HTTPD
+	help
+	This option allows the server to run as a specific user
+	rather than defaulting to the user that starts the server.
+	Use of this option requires special privileges to change to a
+	different user.
+
+config BUSYBOX_CONFIG_FEATURE_HTTPD_BASIC_AUTH
+	bool "Enable HTTP authentication"
+	default BUSYBOX_DEFAULT_FEATURE_HTTPD_BASIC_AUTH
+	depends on BUSYBOX_CONFIG_HTTPD
+	help
+	Utilizes password settings from /etc/httpd.conf for basic
+	authentication on a per url basis.
+	Example for httpd.conf file:
+	/adm:toor:PaSsWd
+
+config BUSYBOX_CONFIG_FEATURE_HTTPD_AUTH_MD5
+	bool "Support MD5-encrypted passwords in HTTP authentication"
+	default BUSYBOX_DEFAULT_FEATURE_HTTPD_AUTH_MD5
+	depends on BUSYBOX_CONFIG_FEATURE_HTTPD_BASIC_AUTH
+	help
+	Enables encrypted passwords, and wildcard user/passwords
+	in httpd.conf file.
+	User '*' means 'any system user name is ok',
+	password of '*' means 'use system password for this user'
+	Examples:
+	/adm:toor:$1$P/eKnWXS$aI1aPGxT.dJD5SzqAKWrF0
+	/adm:root:*
+	/wiki:*:*
+
+config BUSYBOX_CONFIG_FEATURE_HTTPD_CGI
+	bool "Support Common Gateway Interface (CGI)"
+	default BUSYBOX_DEFAULT_FEATURE_HTTPD_CGI
+	depends on BUSYBOX_CONFIG_HTTPD
+	help
+	This option allows scripts and executables to be invoked
+	when specific URLs are requested.
+
+config BUSYBOX_CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR
+	bool "Support running scripts through an interpreter"
+	default BUSYBOX_DEFAULT_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR
+	depends on BUSYBOX_CONFIG_FEATURE_HTTPD_CGI
+	help
+	This option enables support for running scripts through an
+	interpreter. Turn this on if you want PHP scripts to work
+	properly. You need to supply an additional line in your
+	httpd.conf file:
+	*.php:/path/to/your/php
+
+config BUSYBOX_CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV
+	bool "Set REMOTE_PORT environment variable for CGI"
+	default BUSYBOX_DEFAULT_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV
+	depends on BUSYBOX_CONFIG_FEATURE_HTTPD_CGI
+	help
+	Use of this option can assist scripts in generating
+	references that contain a unique port number.
+
+config BUSYBOX_CONFIG_FEATURE_HTTPD_ENCODE_URL_STR
+	bool "Enable -e option (useful for CGIs written as shell scripts)"
+	default BUSYBOX_DEFAULT_FEATURE_HTTPD_ENCODE_URL_STR
+	depends on BUSYBOX_CONFIG_HTTPD
+	help
+	This option allows html encoding of arbitrary strings for display
+	by the browser. Output goes to stdout.
+	For example, httpd -e "<Hello World>" produces
+	"&#60Hello&#32World&#62".
+
+config BUSYBOX_CONFIG_FEATURE_HTTPD_ERROR_PAGES
+	bool "Support custom error pages"
+	default BUSYBOX_DEFAULT_FEATURE_HTTPD_ERROR_PAGES
+	depends on BUSYBOX_CONFIG_HTTPD
+	help
+	This option allows you to define custom error pages in
+	the configuration file instead of the default HTTP status
+	error pages. For instance, if you add the line:
+		E404:/path/e404.html
+	in the config file, the server will respond the specified
+	'/path/e404.html' file instead of the terse '404 NOT FOUND'
+	message.
+
+config BUSYBOX_CONFIG_FEATURE_HTTPD_PROXY
+	bool "Support reverse proxy"
+	default BUSYBOX_DEFAULT_FEATURE_HTTPD_PROXY
+	depends on BUSYBOX_CONFIG_HTTPD
+	help
+	This option allows you to define URLs that will be forwarded
+	to another HTTP server. To setup add the following line to the
+	configuration file
+		P:/url/:http://hostname[:port]/new/path/
+	Then a request to /url/myfile will be forwarded to
+	http://hostname[:port]/new/path/myfile.
+
+config BUSYBOX_CONFIG_FEATURE_HTTPD_GZIP
+	bool "Support GZIP content encoding"
+	default BUSYBOX_DEFAULT_FEATURE_HTTPD_GZIP
+	depends on BUSYBOX_CONFIG_HTTPD
+	help
+	Makes httpd send files using GZIP content encoding if the
+	client supports it and a pre-compressed <file>.gz exists.
+
+config BUSYBOX_CONFIG_FEATURE_HTTPD_ETAG
+	bool "Support caching via ETag header"
+	default BUSYBOX_DEFAULT_FEATURE_HTTPD_ETAG
+	depends on BUSYBOX_CONFIG_HTTPD
+	help
+	If server responds with ETag then next time client (browser)
+	resend it via If-None-Match header.
+	Then httpd will check if file wasn't modified and if not,
+	return 304 Not Modified status code.
+	The ETag value is constructed from last modification date
+	in unix epoch, and size: "hex(last_mod)-hex(file_size)".
+	It's not completely reliable as hash functions but fair enough.
+
+config BUSYBOX_CONFIG_FEATURE_HTTPD_LAST_MODIFIED
+	bool "Add Last-Modified header to response"
+	default BUSYBOX_DEFAULT_FEATURE_HTTPD_LAST_MODIFIED
+	depends on BUSYBOX_CONFIG_HTTPD
+	help
+	The Last-Modified header is used for cache validation.
+	The client sends last seen mtime to server in If-Modified-Since.
+	Both headers MUST be an RFC 1123 formatted, which is hard to parse.
+	Use ETag header instead.
+
+config BUSYBOX_CONFIG_FEATURE_HTTPD_DATE
+	bool "Add Date header to response"
+	default BUSYBOX_DEFAULT_FEATURE_HTTPD_DATE
+	depends on BUSYBOX_CONFIG_HTTPD
+	help
+	RFC2616 says that server MUST add Date header to response.
+	But it is almost useless and can be omitted.
+
+config BUSYBOX_CONFIG_FEATURE_HTTPD_ACL_IP
+	bool "ACL IP"
+	default BUSYBOX_DEFAULT_FEATURE_HTTPD_ACL_IP
+	depends on BUSYBOX_CONFIG_HTTPD
+	help
+	Support IP deny/allow rules
+config BUSYBOX_CONFIG_IFCONFIG
+	bool "ifconfig (12 kb)"
+	default BUSYBOX_DEFAULT_IFCONFIG
+	help
+	Ifconfig is used to configure the kernel-resident network interfaces.
+
+config BUSYBOX_CONFIG_FEATURE_IFCONFIG_STATUS
+	bool "Enable status reporting output (+7k)"
+	default BUSYBOX_DEFAULT_FEATURE_IFCONFIG_STATUS
+	depends on BUSYBOX_CONFIG_IFCONFIG
+	help
+	If ifconfig is called with no arguments it will display the status
+	of the currently active interfaces.
+
+config BUSYBOX_CONFIG_FEATURE_IFCONFIG_SLIP
+	bool "Enable slip-specific options \"keepalive\" and \"outfill\""
+	default BUSYBOX_DEFAULT_FEATURE_IFCONFIG_SLIP
+	depends on BUSYBOX_CONFIG_IFCONFIG
+	help
+	Allow "keepalive" and "outfill" support for SLIP. If you're not
+	planning on using serial lines, leave this unchecked.
+
+config BUSYBOX_CONFIG_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ
+	bool "Enable options \"mem_start\", \"io_addr\", and \"irq\""
+	default BUSYBOX_DEFAULT_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ
+	depends on BUSYBOX_CONFIG_IFCONFIG
+	help
+	Allow the start address for shared memory, start address for I/O,
+	and/or the interrupt line used by the specified device.
+
+config BUSYBOX_CONFIG_FEATURE_IFCONFIG_HW
+	bool "Enable option \"hw\" (ether only)"
+	default BUSYBOX_DEFAULT_FEATURE_IFCONFIG_HW
+	depends on BUSYBOX_CONFIG_IFCONFIG
+	help
+	Set the hardware address of this interface, if the device driver
+	supports  this  operation. Currently, we only support the 'ether'
+	class.
+
+config BUSYBOX_CONFIG_FEATURE_IFCONFIG_BROADCAST_PLUS
+	bool "Set the broadcast automatically"
+	default BUSYBOX_DEFAULT_FEATURE_IFCONFIG_BROADCAST_PLUS
+	depends on BUSYBOX_CONFIG_IFCONFIG
+	help
+	Setting this will make ifconfig attempt to find the broadcast
+	automatically if the value '+' is used.
+config BUSYBOX_CONFIG_IFENSLAVE
+	bool "ifenslave (13 kb)"
+	default BUSYBOX_DEFAULT_IFENSLAVE
+	help
+	Userspace application to bind several interfaces
+	to a logical interface (use with kernel bonding driver).
+config BUSYBOX_CONFIG_IFPLUGD
+	bool "ifplugd (10 kb)"
+	default BUSYBOX_DEFAULT_IFPLUGD
+	help
+	Network interface plug detection daemon.
+config BUSYBOX_CONFIG_IFUP
+	bool "ifup (14 kb)"
+	default BUSYBOX_DEFAULT_IFUP
+	help
+	Activate the specified interfaces. This applet makes use
+	of either "ifconfig" and "route" or the "ip" command to actually
+	configure network interfaces. Therefore, you will probably also want
+	to enable either IFCONFIG and ROUTE, or enable
+	FEATURE_IFUPDOWN_IP and the various IP options. Of
+	course you could use non-busybox versions of these programs, so
+	against my better judgement (since this will surely result in plenty
+	of support questions on the mailing list), I do not force you to
+	enable these additional options. It is up to you to supply either
+	"ifconfig", "route" and "run-parts" or the "ip" command, either
+	via busybox or via standalone utilities.
+
+config BUSYBOX_CONFIG_IFDOWN
+	bool "ifdown (13 kb)"
+	default BUSYBOX_DEFAULT_IFDOWN
+	help
+	Deactivate the specified interfaces.
+
+config BUSYBOX_CONFIG_IFUPDOWN_IFSTATE_PATH
+	string "Absolute path to ifstate file"
+	default BUSYBOX_DEFAULT_IFUPDOWN_IFSTATE_PATH
+	depends on BUSYBOX_CONFIG_IFUP || BUSYBOX_CONFIG_IFDOWN
+	help
+	ifupdown keeps state information in a file called ifstate.
+	Typically it is located in /var/run/ifstate, however
+	some distributions tend to put it in other places
+	(debian, for example, uses /etc/network/run/ifstate).
+	This config option defines location of ifstate.
+
+config BUSYBOX_CONFIG_FEATURE_IFUPDOWN_IP
+	bool "Use ip tool (else ifconfig/route is used)"
+	default BUSYBOX_DEFAULT_FEATURE_IFUPDOWN_IP
+	depends on BUSYBOX_CONFIG_IFUP || BUSYBOX_CONFIG_IFDOWN
+	help
+	Use the iproute "ip" command to implement "ifup" and "ifdown", rather
+	than the default of using the older "ifconfig" and "route" utilities.
+
+	If Y: you must install either the full-blown iproute2 package
+	or enable "ip" applet in busybox, or the "ifup" and "ifdown" applets
+	will not work.
+
+	If N: you must install either the full-blown ifconfig and route
+	utilities, or enable these applets in busybox.
+
+config BUSYBOX_CONFIG_FEATURE_IFUPDOWN_IPV4
+	bool "Support IPv4"
+	default BUSYBOX_DEFAULT_FEATURE_IFUPDOWN_IPV4
+	depends on BUSYBOX_CONFIG_IFUP || BUSYBOX_CONFIG_IFDOWN
+	help
+	If you want ifup/ifdown to talk IPv4, leave this on.
+
+config BUSYBOX_CONFIG_FEATURE_IFUPDOWN_IPV6
+	bool "Support IPv6"
+	default BUSYBOX_DEFAULT_FEATURE_IFUPDOWN_IPV6
+	depends on (BUSYBOX_CONFIG_IFUP || BUSYBOX_CONFIG_IFDOWN) && BUSYBOX_CONFIG_FEATURE_IPV6
+	help
+	If you need support for IPv6, turn this option on.
+
+
+config BUSYBOX_CONFIG_FEATURE_IFUPDOWN_MAPPING
+	bool "Enable mapping support"
+	default BUSYBOX_DEFAULT_FEATURE_IFUPDOWN_MAPPING
+	depends on BUSYBOX_CONFIG_IFUP || BUSYBOX_CONFIG_IFDOWN
+	help
+	This enables support for the "mapping" stanza, unless you have
+	a weird network setup you don't need it.
+
+config BUSYBOX_CONFIG_FEATURE_IFUPDOWN_EXTERNAL_DHCP
+	bool "Support external DHCP clients"
+	default BUSYBOX_DEFAULT_FEATURE_IFUPDOWN_EXTERNAL_DHCP
+	depends on BUSYBOX_CONFIG_IFUP || BUSYBOX_CONFIG_IFDOWN
+	help
+	This enables support for the external dhcp clients. Clients are
+	tried in the following order: dhcpcd, dhclient, pump and udhcpc.
+	Otherwise, if udhcpc applet is enabled, it is used.
+	Otherwise, ifup/ifdown will have no support for DHCP.
+config BUSYBOX_CONFIG_INETD
+	bool "inetd (18 kb)"
+	default BUSYBOX_DEFAULT_INETD
+	select BUSYBOX_CONFIG_FEATURE_SYSLOG
+	help
+	Internet superserver daemon
+
+config BUSYBOX_CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_ECHO
+	bool "Support echo service on port 7"
+	default BUSYBOX_DEFAULT_FEATURE_INETD_SUPPORT_BUILTIN_ECHO
+	depends on BUSYBOX_CONFIG_INETD
+	help
+	Internal service which echoes data back.
+	Activated by configuration lines like these:
+		echo stream tcp nowait root internal
+		echo dgram  udp wait   root internal
+
+config BUSYBOX_CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD
+	bool "Support discard service on port 8"
+	default BUSYBOX_DEFAULT_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD
+	depends on BUSYBOX_CONFIG_INETD
+	help
+	Internal service which discards all input.
+	Activated by configuration lines like these:
+		discard stream tcp nowait root internal
+		discard dgram  udp wait   root internal
+
+config BUSYBOX_CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_TIME
+	bool "Support time service on port 37"
+	default BUSYBOX_DEFAULT_FEATURE_INETD_SUPPORT_BUILTIN_TIME
+	depends on BUSYBOX_CONFIG_INETD
+	help
+	Internal service which returns big-endian 32-bit number
+	of seconds passed since 1900-01-01. The number wraps around
+	on overflow.
+	Activated by configuration lines like these:
+		time stream tcp nowait root internal
+		time dgram  udp wait   root internal
+
+config BUSYBOX_CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME
+	bool "Support daytime service on port 13"
+	default BUSYBOX_DEFAULT_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME
+	depends on BUSYBOX_CONFIG_INETD
+	help
+	Internal service which returns human-readable time.
+	Activated by configuration lines like these:
+		daytime stream tcp nowait root internal
+		daytime dgram  udp wait   root internal
+
+config BUSYBOX_CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN
+	bool "Support chargen service on port 19"
+	default BUSYBOX_DEFAULT_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN
+	depends on BUSYBOX_CONFIG_INETD
+	help
+	Internal service which generates endless stream
+	of all ASCII chars beetween space and char 126.
+	Activated by configuration lines like these:
+		chargen stream tcp nowait root internal
+		chargen dgram  udp wait   root internal
+
+config BUSYBOX_CONFIG_FEATURE_INETD_RPC
+	bool "Support RPC services"
+	default BUSYBOX_DEFAULT_FEATURE_INETD_RPC  # very rarely used, and needs Sun RPC support in libc
+	depends on BUSYBOX_CONFIG_INETD
+	help
+	Support Sun-RPC based services
+config BUSYBOX_CONFIG_IP
+	bool "ip (35 kb)"
+	default BUSYBOX_DEFAULT_IP
+	help
+	The "ip" applet is a TCP/IP interface configuration and routing
+	utility.
+	Short forms (enabled below) are busybox-specific extensions.
+	The standard "ip" utility does not provide them. If you are
+	trying to be portable, it's better to use "ip CMD" forms.
+
+config BUSYBOX_CONFIG_IPADDR
+	bool "ipaddr (14 kb)"
+	default BUSYBOX_DEFAULT_IPADDR
+	select BUSYBOX_CONFIG_FEATURE_IP_ADDRESS
+	help
+	Short form of "ip addr"
+
+config BUSYBOX_CONFIG_IPLINK
+	bool "iplink (17 kb)"
+	default BUSYBOX_DEFAULT_IPLINK
+	select BUSYBOX_CONFIG_FEATURE_IP_LINK
+	help
+	Short form of "ip link"
+
+config BUSYBOX_CONFIG_IPROUTE
+	bool "iproute (15 kb)"
+	default BUSYBOX_DEFAULT_IPROUTE
+	select BUSYBOX_CONFIG_FEATURE_IP_ROUTE
+	help
+	Short form of "ip route"
+
+config BUSYBOX_CONFIG_IPTUNNEL
+	bool "iptunnel (9.6 kb)"
+	default BUSYBOX_DEFAULT_IPTUNNEL
+	select BUSYBOX_CONFIG_FEATURE_IP_TUNNEL
+	help
+	Short form of "ip tunnel"
+
+config BUSYBOX_CONFIG_IPRULE
+	bool "iprule (10 kb)"
+	default BUSYBOX_DEFAULT_IPRULE
+	select BUSYBOX_CONFIG_FEATURE_IP_RULE
+	help
+	Short form of "ip rule"
+
+config BUSYBOX_CONFIG_IPNEIGH
+	bool "ipneigh (8.3 kb)"
+	default BUSYBOX_DEFAULT_IPNEIGH
+	select BUSYBOX_CONFIG_FEATURE_IP_NEIGH
+	help
+	Short form of "ip neigh"
+
+config BUSYBOX_CONFIG_FEATURE_IP_ADDRESS
+	bool "ip address"
+	default BUSYBOX_DEFAULT_FEATURE_IP_ADDRESS
+	depends on BUSYBOX_CONFIG_IP || BUSYBOX_CONFIG_IPADDR
+	help
+	Address manipulation support for the "ip" applet.
+
+config BUSYBOX_CONFIG_FEATURE_IP_LINK
+	bool "ip link"
+	default BUSYBOX_DEFAULT_FEATURE_IP_LINK
+	depends on BUSYBOX_CONFIG_IP || BUSYBOX_CONFIG_IPLINK
+	help
+	Configure network devices with "ip".
+
+config BUSYBOX_CONFIG_FEATURE_IP_ROUTE
+	bool "ip route"
+	default BUSYBOX_DEFAULT_FEATURE_IP_ROUTE
+	depends on BUSYBOX_CONFIG_IP || BUSYBOX_CONFIG_IPROUTE
+	help
+	Add support for routing table management to "ip".
+
+config BUSYBOX_CONFIG_FEATURE_IP_ROUTE_DIR
+	string "ip route configuration directory"
+	default BUSYBOX_DEFAULT_FEATURE_IP_ROUTE_DIR
+	depends on BUSYBOX_CONFIG_FEATURE_IP_ROUTE
+	help
+	Location of the "ip" applet routing configuration.
+
+config BUSYBOX_CONFIG_FEATURE_IP_TUNNEL
+	bool "ip tunnel"
+	default BUSYBOX_DEFAULT_FEATURE_IP_TUNNEL
+	depends on BUSYBOX_CONFIG_IP || BUSYBOX_CONFIG_IPTUNNEL
+	help
+	Add support for tunneling commands to "ip".
+
+config BUSYBOX_CONFIG_FEATURE_IP_RULE
+	bool "ip rule"
+	default BUSYBOX_DEFAULT_FEATURE_IP_RULE
+	depends on BUSYBOX_CONFIG_IP || BUSYBOX_CONFIG_IPRULE
+	help
+	Add support for rule commands to "ip".
+
+config BUSYBOX_CONFIG_FEATURE_IP_NEIGH
+	bool "ip neighbor"
+	default BUSYBOX_DEFAULT_FEATURE_IP_NEIGH
+	depends on BUSYBOX_CONFIG_IP || BUSYBOX_CONFIG_IPNEIGH
+	help
+	Add support for neighbor commands to "ip".
+
+config BUSYBOX_CONFIG_FEATURE_IP_RARE_PROTOCOLS
+	bool "Support displaying rarely used link types"
+	default BUSYBOX_DEFAULT_FEATURE_IP_RARE_PROTOCOLS
+	depends on BUSYBOX_CONFIG_IP || BUSYBOX_CONFIG_IPADDR || BUSYBOX_CONFIG_IPLINK || BUSYBOX_CONFIG_IPROUTE || BUSYBOX_CONFIG_IPTUNNEL || BUSYBOX_CONFIG_IPRULE || BUSYBOX_CONFIG_IPNEIGH
+	help
+	If you are not going to use links of type "frad", "econet",
+	"bif" etc, you probably don't need to enable this.
+	Ethernet, wireless, infrared, ppp/slip, ip tunnelling
+	link types are supported without this option selected.
+config BUSYBOX_CONFIG_IPCALC
+	bool "ipcalc (4.4 kb)"
+	default BUSYBOX_DEFAULT_IPCALC
+	help
+	ipcalc takes an IP address and netmask and calculates the
+	resulting broadcast, network, and host range.
+
+config BUSYBOX_CONFIG_FEATURE_IPCALC_LONG_OPTIONS
+	bool "Enable long options"
+	default BUSYBOX_DEFAULT_FEATURE_IPCALC_LONG_OPTIONS
+	depends on BUSYBOX_CONFIG_IPCALC && BUSYBOX_CONFIG_LONG_OPTS
+
+config BUSYBOX_CONFIG_FEATURE_IPCALC_FANCY
+	bool "Fancy IPCALC, more options, adds 1 kbyte"
+	default BUSYBOX_DEFAULT_FEATURE_IPCALC_FANCY
+	depends on BUSYBOX_CONFIG_IPCALC
+	help
+	Adds the options hostname, prefix and silent to the output of
+	"ipcalc".
+config BUSYBOX_CONFIG_FAKEIDENTD
+	bool "fakeidentd (8.7 kb)"
+	default BUSYBOX_DEFAULT_FAKEIDENTD
+	select BUSYBOX_CONFIG_FEATURE_SYSLOG
+	help
+	fakeidentd listens on the ident port and returns a predefined
+	fake value on any query.
+config BUSYBOX_CONFIG_NAMEIF
+	bool "nameif (6.6 kb)"
+	default BUSYBOX_DEFAULT_NAMEIF
+	select BUSYBOX_CONFIG_FEATURE_SYSLOG
+	help
+	nameif is used to rename network interface by its MAC address.
+	Renamed interfaces MUST be in the down state.
+	It is possible to use a file (default: /etc/mactab)
+	with list of new interface names and MACs.
+	Maximum interface name length: IFNAMSIZ = 16
+	File fields are separated by space or tab.
+	File format:
+		# Comment
+		new_interface_name  XX:XX:XX:XX:XX:XX
+
+config BUSYBOX_CONFIG_FEATURE_NAMEIF_EXTENDED
+	bool "Extended nameif"
+	default BUSYBOX_DEFAULT_FEATURE_NAMEIF_EXTENDED
+	depends on BUSYBOX_CONFIG_NAMEIF
+	help
+	This extends the nameif syntax to support the bus_info, driver,
+	phyaddr selectors. The syntax is compatible to the normal nameif.
+	File format:
+		new_interface_name  driver=asix bus=usb-0000:00:08.2-3
+		new_interface_name  bus=usb-0000:00:08.2-3 00:80:C8:38:91:B5
+		new_interface_name  phy_address=2 00:80:C8:38:91:B5
+		new_interface_name  mac=00:80:C8:38:91:B5
+		new_interface_name  00:80:C8:38:91:B5
+config BUSYBOX_CONFIG_NBDCLIENT
+	bool "nbd-client (6 kb)"
+	default BUSYBOX_DEFAULT_NBDCLIENT
+	help
+	Network block device client
+config BUSYBOX_CONFIG_NC
+	bool "nc (11 kb)"
+	default BUSYBOX_DEFAULT_NC
+	help
+	A simple Unix utility which reads and writes data across network
+	connections.
+
+config BUSYBOX_CONFIG_NETCAT
+	bool "netcat (11 kb)"
+	default BUSYBOX_DEFAULT_NETCAT
+	help
+	Alias to nc.
+
+config BUSYBOX_CONFIG_NC_SERVER
+	bool "Netcat server options (-l)"
+	default BUSYBOX_DEFAULT_NC_SERVER
+	depends on BUSYBOX_CONFIG_NC || BUSYBOX_CONFIG_NETCAT
+	help
+	Allow netcat to act as a server.
+
+config BUSYBOX_CONFIG_NC_EXTRA
+	bool "Netcat extensions (-eiw and -f FILE)"
+	default BUSYBOX_DEFAULT_NC_EXTRA
+	depends on BUSYBOX_CONFIG_NC || BUSYBOX_CONFIG_NETCAT
+	help
+	Add -e (support for executing the rest of the command line after
+	making or receiving a successful connection), -i (delay interval for
+	lines sent), -w (timeout for initial connection).
+
+config BUSYBOX_CONFIG_NC_110_COMPAT
+	bool "Netcat 1.10 compatibility (+2.5k)"
+	default BUSYBOX_DEFAULT_NC_110_COMPAT
+	depends on BUSYBOX_CONFIG_NC || BUSYBOX_CONFIG_NETCAT
+	help
+	This option makes nc closely follow original nc-1.10.
+	The code is about 2.5k bigger. It enables
+	-s ADDR, -n, -u, -v, -o FILE, -z options, but loses
+	busybox-specific extensions: -f FILE.
+config BUSYBOX_CONFIG_NETMSG
+	bool "netmsg"
+	default BUSYBOX_DEFAULT_NETMSG
+	help
+	  simple program for sending udp broadcast messages
+config BUSYBOX_CONFIG_NETSTAT
+	bool "netstat (10 kb)"
+	default BUSYBOX_DEFAULT_NETSTAT
+	help
+	netstat prints information about the Linux networking subsystem.
+
+config BUSYBOX_CONFIG_FEATURE_NETSTAT_WIDE
+	bool "Enable wide output"
+	default BUSYBOX_DEFAULT_FEATURE_NETSTAT_WIDE
+	depends on BUSYBOX_CONFIG_NETSTAT
+	help
+	Add support for wide columns. Useful when displaying IPv6 addresses
+	(-W option).
+
+config BUSYBOX_CONFIG_FEATURE_NETSTAT_PRG
+	bool "Enable PID/Program name output"
+	default BUSYBOX_DEFAULT_FEATURE_NETSTAT_PRG
+	depends on BUSYBOX_CONFIG_NETSTAT
+	help
+	Add support for -p flag to print out PID and program name.
+	+700 bytes of code.
+config BUSYBOX_CONFIG_NSLOOKUP
+	bool "nslookup (9.7 kb)"
+	default BUSYBOX_DEFAULT_NSLOOKUP
+	help
+	nslookup is a tool to query Internet name servers.
+
+config BUSYBOX_CONFIG_FEATURE_NSLOOKUP_BIG
+	bool "Use internal resolver code instead of libc"
+	depends on BUSYBOX_CONFIG_NSLOOKUP
+	default BUSYBOX_DEFAULT_FEATURE_NSLOOKUP_BIG
+
+config BUSYBOX_CONFIG_FEATURE_NSLOOKUP_LONG_OPTIONS
+	bool "Enable long options"
+	default BUSYBOX_DEFAULT_FEATURE_NSLOOKUP_LONG_OPTIONS
+	depends on BUSYBOX_CONFIG_FEATURE_NSLOOKUP_BIG && BUSYBOX_CONFIG_LONG_OPTS
+config BUSYBOX_CONFIG_NTPD
+	bool "ntpd (22 kb)"
+	default BUSYBOX_DEFAULT_NTPD
+	help
+	The NTP client/server daemon.
+
+config BUSYBOX_CONFIG_FEATURE_NTPD_SERVER
+	bool "Make ntpd usable as a NTP server"
+	default BUSYBOX_DEFAULT_FEATURE_NTPD_SERVER
+	depends on BUSYBOX_CONFIG_NTPD
+	help
+	Make ntpd usable as a NTP server. If you disable this option
+	ntpd will be usable only as a NTP client.
+
+config BUSYBOX_CONFIG_FEATURE_NTPD_CONF
+	bool "Make ntpd understand /etc/ntp.conf"
+	default BUSYBOX_DEFAULT_FEATURE_NTPD_CONF
+	depends on BUSYBOX_CONFIG_NTPD
+	help
+	Make ntpd look in /etc/ntp.conf for peers. Only "server address"
+	is supported.
+
+config BUSYBOX_CONFIG_FEATURE_NTP_AUTH
+	bool "Support md5/sha1 message authentication codes"
+	default BUSYBOX_DEFAULT_FEATURE_NTP_AUTH
+	depends on BUSYBOX_CONFIG_NTPD
+config BUSYBOX_CONFIG_PING
+	bool "ping (10 kb)"
+	default BUSYBOX_DEFAULT_PING
+	help
+	ping uses the ICMP protocol's mandatory ECHO_REQUEST datagram to
+	elicit an ICMP ECHO_RESPONSE from a host or gateway.
+
+config BUSYBOX_CONFIG_PING6
+	bool "ping6 (11 kb)"
+	default BUSYBOX_DEFAULT_PING6
+	depends on BUSYBOX_CONFIG_FEATURE_IPV6
+	help
+	Alias to "ping -6".
+
+config BUSYBOX_CONFIG_FEATURE_FANCY_PING
+	bool "Enable fancy ping output"
+	default BUSYBOX_DEFAULT_FEATURE_FANCY_PING
+	depends on BUSYBOX_CONFIG_PING || BUSYBOX_CONFIG_PING6
+	help
+	With this option off, ping will say "HOST is alive!"
+	or terminate with SIGALRM in 5 seconds otherwise.
+	No command-line options will be recognized.
+config BUSYBOX_CONFIG_PSCAN
+	bool "pscan (6 kb)"
+	default BUSYBOX_DEFAULT_PSCAN
+	help
+	Simple network port scanner.
+config BUSYBOX_CONFIG_ROUTE
+	bool "route (8.7 kb)"
+	default BUSYBOX_DEFAULT_ROUTE
+	help
+	Route displays or manipulates the kernel's IP routing tables.
+config BUSYBOX_CONFIG_SLATTACH
+	bool "slattach (6.2 kb)"
+	default BUSYBOX_DEFAULT_SLATTACH
+	help
+	slattach configures serial line as SLIP network interface.
+config BUSYBOX_CONFIG_SSL_CLIENT
+	bool "ssl_client (25 kb)"
+	default BUSYBOX_DEFAULT_SSL_CLIENT
+	select BUSYBOX_CONFIG_TLS
+	help
+	This tool pipes data to/from a socket, TLS-encrypting it.
+config BUSYBOX_CONFIG_TC
+	bool "tc (8.3 kb)"
+	default BUSYBOX_DEFAULT_TC
+	help
+	Show / manipulate traffic control settings
+
+config BUSYBOX_CONFIG_FEATURE_TC_INGRESS
+	bool "Enable ingress"
+	default BUSYBOX_DEFAULT_FEATURE_TC_INGRESS
+	depends on BUSYBOX_CONFIG_TC
+config BUSYBOX_CONFIG_TCPSVD
+	bool "tcpsvd (14 kb)"
+	default BUSYBOX_DEFAULT_TCPSVD
+	help
+	tcpsvd listens on a TCP port and runs a program for each new
+	connection.
+
+config BUSYBOX_CONFIG_UDPSVD
+	bool "udpsvd (13 kb)"
+	default BUSYBOX_DEFAULT_UDPSVD
+	help
+	udpsvd listens on an UDP port and runs a program for each new
+	connection.
+config BUSYBOX_CONFIG_TELNET
+	bool "telnet (8.8 kb)"
+	default BUSYBOX_DEFAULT_TELNET
+	help
+	Telnet is an interface to the TELNET protocol, but is also commonly
+	used to test other simple protocols.
+
+config BUSYBOX_CONFIG_FEATURE_TELNET_TTYPE
+	bool "Pass TERM type to remote host"
+	default BUSYBOX_DEFAULT_FEATURE_TELNET_TTYPE
+	depends on BUSYBOX_CONFIG_TELNET
+	help
+	Setting this option will forward the TERM environment variable to the
+	remote host you are connecting to. This is useful to make sure that
+	things like ANSI colors and other control sequences behave.
+
+config BUSYBOX_CONFIG_FEATURE_TELNET_AUTOLOGIN
+	bool "Pass USER type to remote host"
+	default BUSYBOX_DEFAULT_FEATURE_TELNET_AUTOLOGIN
+	depends on BUSYBOX_CONFIG_TELNET
+	help
+	Setting this option will forward the USER environment variable to the
+	remote host you are connecting to. This is useful when you need to
+	log into a machine without telling the username (autologin). This
+	option enables '-a' and '-l USER' options.
+
+config BUSYBOX_CONFIG_FEATURE_TELNET_WIDTH
+	bool "Enable window size autodetection"
+	default BUSYBOX_DEFAULT_FEATURE_TELNET_WIDTH
+	depends on BUSYBOX_CONFIG_TELNET
+config BUSYBOX_CONFIG_TELNETD
+	bool "telnetd (12 kb)"
+	default BUSYBOX_DEFAULT_TELNETD
+	select BUSYBOX_CONFIG_FEATURE_SYSLOG
+	help
+	A daemon for the TELNET protocol, allowing you to log onto the host
+	running the daemon. Please keep in mind that the TELNET protocol
+	sends passwords in plain text. If you can't afford the space for an
+	SSH daemon and you trust your network, you may say 'y' here. As a
+	more secure alternative, you should seriously consider installing the
+	very small Dropbear SSH daemon instead:
+		http://matt.ucc.asn.au/dropbear/dropbear.html
+
+	Note that for busybox telnetd to work you need several things:
+	First of all, your kernel needs:
+		  CONFIG_UNIX98_PTYS=y
+
+	Next, you need a /dev/pts directory on your root filesystem:
+
+		  $ ls -ld /dev/pts
+		  drwxr-xr-x  2 root root 0 Sep 23 13:21 /dev/pts/
+
+	Next you need the pseudo terminal master multiplexer /dev/ptmx:
+
+		  $ ls -la /dev/ptmx
+		  crw-rw-rw-  1 root tty 5, 2 Sep 23 13:55 /dev/ptmx
+
+	Any /dev/ttyp[0-9]* files you may have can be removed.
+	Next, you need to mount the devpts filesystem on /dev/pts using:
+
+		  mount -t devpts devpts /dev/pts
+
+	You need to be sure that busybox has LOGIN and
+	FEATURE_SUID enabled. And finally, you should make
+	certain that busybox has been installed setuid root:
+
+		chown root.root /bin/busybox
+		chmod 4755 /bin/busybox
+
+	with all that done, telnetd _should_ work....
+
+config BUSYBOX_CONFIG_FEATURE_TELNETD_STANDALONE
+	bool "Support standalone telnetd (not inetd only)"
+	default BUSYBOX_DEFAULT_FEATURE_TELNETD_STANDALONE
+	depends on BUSYBOX_CONFIG_TELNETD
+	help
+	Selecting this will make telnetd able to run standalone.
+
+config BUSYBOX_CONFIG_FEATURE_TELNETD_PORT_DEFAULT
+	int "Default port"
+	default BUSYBOX_DEFAULT_FEATURE_TELNETD_PORT_DEFAULT
+	range 1 65535
+	depends on BUSYBOX_CONFIG_FEATURE_TELNETD_STANDALONE
+
+config BUSYBOX_CONFIG_FEATURE_TELNETD_INETD_WAIT
+	bool "Support -w SEC option (inetd wait mode)"
+	default BUSYBOX_DEFAULT_FEATURE_TELNETD_INETD_WAIT
+	depends on BUSYBOX_CONFIG_FEATURE_TELNETD_STANDALONE
+	help
+	This option allows you to run telnetd in "inet wait" mode.
+	Example inetd.conf line (note "wait", not usual "nowait"):
+
+	telnet stream tcp wait root /bin/telnetd telnetd -w10
+
+	In this example, inetd passes _listening_ socket_ as fd 0
+	to telnetd when connection appears.
+	telnetd will wait for connections until all existing
+	connections are closed, and no new connections
+	appear during 10 seconds. Then it exits, and inetd continues
+	to listen for new connections.
+
+	This option is rarely used. "tcp nowait" is much more usual
+	way of running tcp services, including telnetd.
+	You most probably want to say N here.
+config BUSYBOX_CONFIG_TFTP
+	bool "tftp (11 kb)"
+	default BUSYBOX_DEFAULT_TFTP
+	help
+	Trivial File Transfer Protocol client. TFTP is usually used
+	for simple, small transfers such as a root image
+	for a network-enabled bootloader.
+
+config BUSYBOX_CONFIG_FEATURE_TFTP_PROGRESS_BAR
+	bool "Enable progress bar"
+	default BUSYBOX_DEFAULT_FEATURE_TFTP_PROGRESS_BAR
+	depends on BUSYBOX_CONFIG_TFTP
+
+config BUSYBOX_CONFIG_FEATURE_TFTP_HPA_COMPAT
+	bool "tftp-hpa compat (support -c get/put FILE)"
+	default BUSYBOX_DEFAULT_FEATURE_TFTP_HPA_COMPAT
+	depends on BUSYBOX_CONFIG_TFTP
+
+config BUSYBOX_CONFIG_TFTPD
+	bool "tftpd (10 kb)"
+	default BUSYBOX_DEFAULT_TFTPD
+	help
+	Trivial File Transfer Protocol server.
+	It expects that stdin is a datagram socket and a packet
+	is already pending on it. It will exit after one transfer.
+	In other words: it should be run from inetd in nowait mode,
+	or from udpsvd. Example: "udpsvd -E 0 69 tftpd DIR"
+
+config BUSYBOX_CONFIG_FEATURE_TFTP_GET
+	bool "Enable 'tftp get' and/or tftpd upload code"
+	default BUSYBOX_DEFAULT_FEATURE_TFTP_GET
+	depends on BUSYBOX_CONFIG_TFTP || BUSYBOX_CONFIG_TFTPD
+	help
+	Add support for the GET command within the TFTP client. This allows
+	a client to retrieve a file from a TFTP server.
+	Also enable upload support in tftpd, if tftpd is selected.
+
+	Note: this option does _not_ make tftpd capable of download
+	(the usual operation people need from it)!
+
+config BUSYBOX_CONFIG_FEATURE_TFTP_PUT
+	bool "Enable 'tftp put' and/or tftpd download code"
+	default BUSYBOX_DEFAULT_FEATURE_TFTP_PUT
+	depends on BUSYBOX_CONFIG_TFTP || BUSYBOX_CONFIG_TFTPD
+	help
+	Add support for the PUT command within the TFTP client. This allows
+	a client to transfer a file to a TFTP server.
+	Also enable download support in tftpd, if tftpd is selected.
+
+config BUSYBOX_CONFIG_FEATURE_TFTP_BLOCKSIZE
+	bool "Enable 'blksize' and 'tsize' protocol options"
+	default BUSYBOX_DEFAULT_FEATURE_TFTP_BLOCKSIZE
+	depends on BUSYBOX_CONFIG_TFTP || BUSYBOX_CONFIG_TFTPD
+	help
+	Allow tftp to specify block size, and tftpd to understand
+	"blksize" and "tsize" options.
+
+config BUSYBOX_CONFIG_TFTP_DEBUG
+	bool "Enable debug"
+	default BUSYBOX_DEFAULT_TFTP_DEBUG
+	depends on BUSYBOX_CONFIG_TFTP || BUSYBOX_CONFIG_TFTPD
+	help
+	Make tftp[d] print debugging messages on stderr.
+	This is useful if you are diagnosing a bug in tftp[d].
+config BUSYBOX_CONFIG_TLS
+	bool #No description makes it a hidden option
+	default BUSYBOX_DEFAULT_TLS
+config BUSYBOX_CONFIG_TRACEROUTE
+	bool "traceroute (11 kb)"
+	default BUSYBOX_DEFAULT_TRACEROUTE
+	help
+	Utility to trace the route of IP packets.
+
+config BUSYBOX_CONFIG_TRACEROUTE6
+	bool "traceroute6 (13 kb)"
+	default BUSYBOX_DEFAULT_TRACEROUTE6
+	depends on BUSYBOX_CONFIG_FEATURE_IPV6
+	help
+	Utility to trace the route of IPv6 packets.
+
+config BUSYBOX_CONFIG_FEATURE_TRACEROUTE_VERBOSE
+	bool "Enable verbose output"
+	default BUSYBOX_DEFAULT_FEATURE_TRACEROUTE_VERBOSE
+	depends on BUSYBOX_CONFIG_TRACEROUTE || BUSYBOX_CONFIG_TRACEROUTE6
+	help
+	Add some verbosity to traceroute. This includes among other things
+	hostnames and ICMP response types.
+
+config BUSYBOX_CONFIG_FEATURE_TRACEROUTE_USE_ICMP
+	bool "Enable -I option (use ICMP instead of UDP)"
+	default BUSYBOX_DEFAULT_FEATURE_TRACEROUTE_USE_ICMP
+	depends on BUSYBOX_CONFIG_TRACEROUTE || BUSYBOX_CONFIG_TRACEROUTE6
+config BUSYBOX_CONFIG_TUNCTL
+	bool "tunctl (6.2 kb)"
+	default BUSYBOX_DEFAULT_TUNCTL
+	help
+	tunctl creates or deletes tun devices.
+
+config BUSYBOX_CONFIG_FEATURE_TUNCTL_UG
+	bool "Support owner:group assignment"
+	default BUSYBOX_DEFAULT_FEATURE_TUNCTL_UG
+	depends on BUSYBOX_CONFIG_TUNCTL
+	help
+	Allow to specify owner and group of newly created interface.
+	340 bytes of pure bloat. Say no here.
+config BUSYBOX_CONFIG_VCONFIG
+	bool "vconfig (2.3 kb)"
+	default BUSYBOX_DEFAULT_VCONFIG
+	help
+	Creates, removes, and configures VLAN interfaces
+config BUSYBOX_CONFIG_WGET
+	bool "wget (38 kb)"
+	default BUSYBOX_DEFAULT_WGET
+	help
+	wget is a utility for non-interactive download of files from HTTP
+	and FTP servers.
+
+config BUSYBOX_CONFIG_FEATURE_WGET_LONG_OPTIONS
+	bool "Enable long options"
+	default BUSYBOX_DEFAULT_FEATURE_WGET_LONG_OPTIONS
+	depends on BUSYBOX_CONFIG_WGET && BUSYBOX_CONFIG_LONG_OPTS
+
+config BUSYBOX_CONFIG_FEATURE_WGET_STATUSBAR
+	bool "Enable progress bar (+2k)"
+	default BUSYBOX_DEFAULT_FEATURE_WGET_STATUSBAR
+	depends on BUSYBOX_CONFIG_WGET
+
+config BUSYBOX_CONFIG_FEATURE_WGET_FTP
+	bool "Enable FTP protocol (+1k)"
+	default BUSYBOX_DEFAULT_FEATURE_WGET_FTP
+	depends on BUSYBOX_CONFIG_WGET
+	help
+	To support FTPS, enable FEATURE_WGET_HTTPS as well.
+
+config BUSYBOX_CONFIG_FEATURE_WGET_AUTHENTICATION
+	bool "Enable HTTP authentication"
+	default BUSYBOX_DEFAULT_FEATURE_WGET_AUTHENTICATION
+	depends on BUSYBOX_CONFIG_WGET
+	help
+	Support authenticated HTTP transfers.
+
+config BUSYBOX_CONFIG_FEATURE_WGET_TIMEOUT
+	bool "Enable timeout option -T SEC"
+	default BUSYBOX_DEFAULT_FEATURE_WGET_TIMEOUT
+	depends on BUSYBOX_CONFIG_WGET
+	help
+	Supports network read and connect timeouts for wget,
+	so that wget will give up and timeout, through the -T
+	command line option.
+
+	Currently only connect and network data read timeout are
+	supported (i.e., timeout is not applied to the DNS query). When
+	FEATURE_WGET_LONG_OPTIONS is also enabled, the --timeout option
+	will work in addition to -T.
+
+config BUSYBOX_CONFIG_FEATURE_WGET_HTTPS
+	bool "Support HTTPS using internal TLS code"
+	default BUSYBOX_DEFAULT_FEATURE_WGET_HTTPS
+	depends on BUSYBOX_CONFIG_WGET
+	select BUSYBOX_CONFIG_TLS
+	help
+	wget will use internal TLS code to connect to https:// URLs.
+	It also enables FTPS support, but it's not well tested yet.
+	Note:
+	On NOMMU machines, ssl_helper applet should be available
+	in the $PATH for this to work. Make sure to select that applet.
+
+	Note: currently, TLS code only makes TLS I/O work, it
+	does *not* check that the peer is who it claims to be, etc.
+	IOW: it uses peer-supplied public keys to establish encryption
+	and signing keys, then encrypts and signs outgoing data and
+	decrypts incoming data.
+	It does not check signature hashes on the incoming data:
+	this means that attackers manipulating TCP packets can
+	send altered data and we unknowingly receive garbage.
+	(This check might be relatively easy to add).
+	It does not check public key's certificate:
+	this means that the peer may be an attacker impersonating
+	the server we think we are talking to.
+
+	If you think this is unacceptable, consider this. As more and more
+	servers switch to HTTPS-only operation, without such "crippled"
+	TLS code it is *impossible* to simply download a kernel source
+	from kernel.org. Which can in real world translate into
+	"my small automatic tooling to build cross-compilers from sources
+	no longer works, I need to additionally keep a local copy
+	of ~4 megabyte source tarball of a SSL library and ~2 megabyte
+	source of wget, need to compile and built both before I can
+	download anything. All this despite the fact that the build
+	is done in a QEMU sandbox on a machine with absolutely nothing
+	worth stealing, so I don't care if someone would go to a lot
+	of trouble to intercept my HTTPS download to send me an altered
+	kernel tarball".
+
+	If you still think this is unacceptable, send patches.
+
+	If you still think this is unacceptable, do not want to send
+	patches, but do want to waste bandwidth expaining how wrong
+	it is, you will be ignored.
+
+	FEATURE_WGET_OPENSSL does implement TLS verification
+	using the certificates available to OpenSSL.
+
+config BUSYBOX_CONFIG_FEATURE_WGET_OPENSSL
+	bool "Try to connect to HTTPS using openssl"
+	default BUSYBOX_DEFAULT_FEATURE_WGET_OPENSSL
+	depends on BUSYBOX_CONFIG_WGET
+	help
+	Try to use openssl to handle HTTPS.
+
+	OpenSSL has a simple SSL client for debug purposes.
+	If you select this option, wget will effectively run:
+	"openssl s_client -quiet -connect hostname:443
+	-servername hostname 2>/dev/null" and pipe its data
+	through it. -servername is not used if hostname is numeric.
+	Note inconvenient API: host resolution is done twice,
+	and there is no guarantee openssl's idea of IPv6 address
+	format is the same as ours.
+	Another problem is that s_client prints debug information
+	to stderr, and it needs to be suppressed. This means
+	all error messages get suppressed too.
+	openssl is also a big binary, often dynamically linked
+	against ~15 libraries.
+
+	If openssl can't be executed, internal TLS code will be used
+	(if you enabled it); if openssl can be executed but fails later,
+	wget can't detect this, and download will fail.
+
+	By default TLS verification is performed, unless
+	--no-check-certificate option is passed.
+config BUSYBOX_CONFIG_WHOIS
+	bool "whois (6.3 kb)"
+	default BUSYBOX_DEFAULT_WHOIS
+	help
+	whois is a client for the whois directory service
+config BUSYBOX_CONFIG_ZCIP
+	bool "zcip (8.4 kb)"
+	default BUSYBOX_DEFAULT_ZCIP
+	select BUSYBOX_CONFIG_FEATURE_SYSLOG
+	help
+	ZCIP provides ZeroConf IPv4 address selection, according to RFC 3927.
+	It's a daemon that allocates and defends a dynamically assigned
+	address on the 169.254/16 network, requiring no system administrator.
+
+	See http://www.zeroconf.org for further details, and "zcip.script"
+	in the busybox examples.
+
+source "udhcp/Config.in"
+
+config BUSYBOX_CONFIG_IFUPDOWN_UDHCPC_CMD_OPTIONS
+	string "ifup udhcpc command line options"
+	default BUSYBOX_DEFAULT_IFUPDOWN_UDHCPC_CMD_OPTIONS
+	depends on BUSYBOX_CONFIG_IFUP || BUSYBOX_CONFIG_IFDOWN
+	help
+	Command line options to pass to udhcpc from ifup.
+	Intended to alter options not available in /etc/network/interfaces.
+	(IE: --syslog --background etc...)
+
+endmenu
diff --git a/package/utils/busybox/config/networking/udhcp/Config.in b/package/utils/busybox/config/networking/udhcp/Config.in
new file mode 100644
index 0000000..6757f1e
--- /dev/null
+++ b/package/utils/busybox/config/networking/udhcp/Config.in
@@ -0,0 +1,216 @@
+# DO NOT EDIT. This file is generated from Config.src
+#
+# For a description of the syntax of this configuration file,
+# see docs/Kconfig-language.txt.
+#
+
+config BUSYBOX_CONFIG_UDHCPD
+	bool "udhcpd (21 kb)"
+	default BUSYBOX_DEFAULT_UDHCPD
+	help
+	udhcpd is a DHCP server geared primarily toward embedded systems,
+	while striving to be fully functional and RFC compliant.
+
+config BUSYBOX_CONFIG_FEATURE_UDHCPD_BASE_IP_ON_MAC
+	bool "Select IP address based on client MAC"
+	default BUSYBOX_DEFAULT_FEATURE_UDHCPD_BASE_IP_ON_MAC
+	depends on BUSYBOX_CONFIG_UDHCPD
+	help
+	If selected, udhcpd will base its selection of IP address to offer
+	on the client's hardware address. Otherwise udhcpd uses the next
+	consecutive free address.
+
+	This reduces the frequency of IP address changes for clients
+	which let their lease expire, and makes consecutive DHCPOFFERS
+	for the same client to (almost always) contain the same
+	IP address.
+
+config BUSYBOX_CONFIG_FEATURE_UDHCPD_WRITE_LEASES_EARLY
+	bool "Rewrite lease file at every new acknowledge"
+	default BUSYBOX_DEFAULT_FEATURE_UDHCPD_WRITE_LEASES_EARLY
+	depends on BUSYBOX_CONFIG_UDHCPD
+	help
+	If selected, udhcpd will write a new file with leases every
+	time a new lease has been accepted, thus eliminating the need
+	to send SIGUSR1 for the initial writing or updating. Any timed
+	rewriting remains undisturbed.
+
+config BUSYBOX_CONFIG_DHCPD_LEASES_FILE
+	string "Absolute path to lease file"
+	default BUSYBOX_DEFAULT_DHCPD_LEASES_FILE
+	depends on BUSYBOX_CONFIG_UDHCPD
+	help
+	udhcpd stores addresses in a lease file. This is the absolute path
+	of the file. Normally it is safe to leave it untouched.
+
+config BUSYBOX_CONFIG_DUMPLEASES
+	bool "dumpleases (5.1 kb)"
+	default BUSYBOX_DEFAULT_DUMPLEASES
+	help
+	dumpleases displays the leases written out by the udhcpd.
+	Lease times are stored in the file by time remaining in lease, or
+	by the absolute time that it expires in seconds from epoch.
+
+config BUSYBOX_CONFIG_DHCPRELAY
+	bool "dhcprelay (5.2 kb)"
+	default BUSYBOX_DEFAULT_DHCPRELAY
+	help
+	dhcprelay listens for DHCP requests on one or more interfaces
+	and forwards these requests to a different interface or DHCP
+	server.
+
+config BUSYBOX_CONFIG_UDHCPC
+	bool "udhcpc (24 kb)"
+	default BUSYBOX_DEFAULT_UDHCPC
+	help
+	udhcpc is a DHCP client geared primarily toward embedded systems,
+	while striving to be fully functional and RFC compliant.
+
+	The udhcp client negotiates a lease with the DHCP server and
+	runs a script when a lease is obtained or lost.
+
+config BUSYBOX_CONFIG_FEATURE_UDHCPC_ARPING
+	bool "Verify that the offered address is free, using ARP ping"
+	default BUSYBOX_DEFAULT_FEATURE_UDHCPC_ARPING
+	depends on BUSYBOX_CONFIG_UDHCPC
+	help
+	If selected, udhcpc will send ARP probes and make sure
+	the offered address is really not in use by anyone. The client
+	will DHCPDECLINE the offer if the address is in use,
+	and restart the discover process.
+
+config BUSYBOX_CONFIG_FEATURE_UDHCPC_SANITIZEOPT
+	bool "Do not pass malformed host and domain names"
+	default BUSYBOX_DEFAULT_FEATURE_UDHCPC_SANITIZEOPT
+	depends on BUSYBOX_CONFIG_UDHCPC
+	help
+	If selected, udhcpc will check some options (such as option 12 -
+	hostname) and if they don't look like valid hostnames
+	(for example, if they start with dash or contain spaces),
+	they will be replaced with string "bad" when exporting
+	to the environment.
+
+config BUSYBOX_CONFIG_UDHCPC_DEFAULT_SCRIPT
+	string "Absolute path to config script"
+	default BUSYBOX_DEFAULT_UDHCPC_DEFAULT_SCRIPT
+	depends on BUSYBOX_CONFIG_UDHCPC
+	help
+	This script is called after udhcpc receives an answer. See
+	examples/udhcp for a working example. Normally it is safe
+	to leave this untouched.
+
+config BUSYBOX_CONFIG_UDHCPC6_DEFAULT_SCRIPT
+	string "Absolute path to config script for IPv6"
+	default BUSYBOX_DEFAULT_UDHCPC6_DEFAULT_SCRIPT
+	depends on BUSYBOX_CONFIG_UDHCPC6
+
+# udhcpc6 config is inserted here:
+config BUSYBOX_CONFIG_UDHCPC6
+	bool "udhcpc6 (21 kb)"
+	default BUSYBOX_DEFAULT_UDHCPC6
+	depends on BUSYBOX_CONFIG_FEATURE_IPV6
+	help
+	udhcpc6 is a DHCPv6 client
+
+config BUSYBOX_CONFIG_FEATURE_UDHCPC6_RFC3646
+	bool "Support RFC 3646 (DNS server and search list)"
+	default BUSYBOX_DEFAULT_FEATURE_UDHCPC6_RFC3646
+	depends on BUSYBOX_CONFIG_UDHCPC6
+	help
+	List of DNS servers and domain search list can be requested with
+	"-O dns" and "-O search". If server gives these values,
+	they will be set in environment variables "dns" and "search".
+
+config BUSYBOX_CONFIG_FEATURE_UDHCPC6_RFC4704
+	bool "Support RFC 4704 (Client FQDN)"
+	default BUSYBOX_DEFAULT_FEATURE_UDHCPC6_RFC4704
+	depends on BUSYBOX_CONFIG_UDHCPC6
+	help
+	You can request FQDN to be given by server using "-O fqdn".
+
+config BUSYBOX_CONFIG_FEATURE_UDHCPC6_RFC4833
+	bool "Support RFC 4833 (Timezones)"
+	default BUSYBOX_DEFAULT_FEATURE_UDHCPC6_RFC4833
+	depends on BUSYBOX_CONFIG_UDHCPC6
+	help
+	You can request POSIX timezone with "-O tz" and timezone name
+	with "-O timezone".
+
+config BUSYBOX_CONFIG_FEATURE_UDHCPC6_RFC5970
+	bool "Support RFC 5970 (Network Boot)"
+	default BUSYBOX_DEFAULT_FEATURE_UDHCPC6_RFC5970
+	depends on BUSYBOX_CONFIG_UDHCPC6
+	help
+	You can request bootfile-url with "-O bootfile_url" and
+	bootfile-params with "-O bootfile_params".
+
+comment "Common options for DHCP applets"
+        depends on BUSYBOX_CONFIG_UDHCPD || BUSYBOX_CONFIG_UDHCPC || BUSYBOX_CONFIG_UDHCPC6 || BUSYBOX_CONFIG_DHCPRELAY
+
+config BUSYBOX_CONFIG_UDHCPC_DEFAULT_INTERFACE
+	string "Default interface name"
+	default BUSYBOX_DEFAULT_UDHCPC_DEFAULT_INTERFACE
+	depends on BUSYBOX_CONFIG_UDHCPC || BUSYBOX_CONFIG_UDHCPC6
+	help
+	The interface that will be used if no other interface is
+	specified on the commandline.
+
+config BUSYBOX_CONFIG_FEATURE_UDHCP_PORT
+	bool "Enable '-P port' option for udhcpd and udhcpc"
+	default BUSYBOX_DEFAULT_FEATURE_UDHCP_PORT
+	depends on BUSYBOX_CONFIG_UDHCPD || BUSYBOX_CONFIG_UDHCPC || BUSYBOX_CONFIG_UDHCPC6
+	help
+	At the cost of ~300 bytes, enables -P port option.
+	This feature is typically not needed.
+
+config BUSYBOX_CONFIG_UDHCP_DEBUG
+	int "Maximum verbosity level (0..9)"
+	default BUSYBOX_DEFAULT_UDHCP_DEBUG
+	range 0 9
+	depends on BUSYBOX_CONFIG_UDHCPD || BUSYBOX_CONFIG_UDHCPC || BUSYBOX_CONFIG_UDHCPC6 || BUSYBOX_CONFIG_DHCPRELAY
+	help
+	Verbosity can be increased with multiple -v options.
+	This option controls how high it can be cranked up.
+
+	Bigger values result in bigger code. Levels above 1
+	are very verbose and useful for debugging only.
+
+config BUSYBOX_CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS
+	int "DHCP options slack buffer size"
+	default BUSYBOX_DEFAULT_UDHCPC_SLACK_FOR_BUGGY_SERVERS
+	range 0 924
+	depends on BUSYBOX_CONFIG_UDHCPD || BUSYBOX_CONFIG_UDHCPC
+	help
+	Some buggy DHCP servers send DHCP offer packets with option
+	field larger than we expect (which might also be considered a
+	buffer overflow attempt). These packets are normally discarded.
+	If circumstances beyond your control force you to support such
+	servers, this may help. The upper limit (924) makes udhcpc accept
+	even 1500 byte packets (maximum-sized ethernet packets).
+
+	This option does not make udhcp[cd] emit non-standard
+	sized packets.
+
+	Known buggy DHCP servers:
+	3Com OfficeConnect Remote 812 ADSL Router:
+		seems to confuse maximum allowed UDP packet size with
+		maximum size of entire IP packet, and sends packets
+		which are 28 bytes too large.
+	Seednet (ISP) VDSL: sends packets 2 bytes too large.
+
+config BUSYBOX_CONFIG_FEATURE_UDHCP_RFC3397
+	bool "Support RFC 3397 domain search options"
+	default BUSYBOX_DEFAULT_FEATURE_UDHCP_RFC3397
+	depends on BUSYBOX_CONFIG_UDHCPD || BUSYBOX_CONFIG_UDHCPC
+	help
+	If selected, both client and server will support passing of domain
+	search lists via option 119, specified in RFC 3397,
+	and SIP servers option 120, specified in RFC 3361.
+
+config BUSYBOX_CONFIG_FEATURE_UDHCP_8021Q
+	bool "Support 802.1Q VLAN parameters options"
+	default BUSYBOX_DEFAULT_FEATURE_UDHCP_8021Q
+	depends on BUSYBOX_CONFIG_UDHCPD || BUSYBOX_CONFIG_UDHCPC
+	help
+	If selected, both client and server will support passing of VLAN
+	ID and priority via options 132 and 133 as per 802.1Q.
diff --git a/package/utils/busybox/config/printutils/Config.in b/package/utils/busybox/config/printutils/Config.in
new file mode 100644
index 0000000..c53ee19
--- /dev/null
+++ b/package/utils/busybox/config/printutils/Config.in
@@ -0,0 +1,26 @@
+# DO NOT EDIT. This file is generated from Config.src
+#
+# For a description of the syntax of this configuration file,
+# see docs/Kconfig-language.txt.
+#
+
+menu "Print Utilities"
+
+config BUSYBOX_CONFIG_LPD
+	bool "lpd (5.5 kb)"
+	default BUSYBOX_DEFAULT_LPD
+	help
+	lpd is a print spooling daemon.
+config BUSYBOX_CONFIG_LPR
+	bool "lpr (9.9 kb)"
+	default BUSYBOX_DEFAULT_LPR
+	help
+	lpr sends files (or standard input) to a print spooling daemon.
+
+config BUSYBOX_CONFIG_LPQ
+	bool "lpq (9.9 kb)"
+	default BUSYBOX_DEFAULT_LPQ
+	help
+	lpq is a print spool queue examination and manipulation program.
+
+endmenu
diff --git a/package/utils/busybox/config/procps/Config.in b/package/utils/busybox/config/procps/Config.in
new file mode 100644
index 0000000..0501daf
--- /dev/null
+++ b/package/utils/busybox/config/procps/Config.in
@@ -0,0 +1,277 @@
+# DO NOT EDIT. This file is generated from Config.src
+#
+# For a description of the syntax of this configuration file,
+# see docs/Kconfig-language.txt.
+#
+
+menu "Process Utilities"
+
+config BUSYBOX_CONFIG_FEATURE_FAST_TOP
+	bool "Faster /proc scanning code (+100 bytes)"
+	default BUSYBOX_DEFAULT_FEATURE_FAST_TOP  # all "fast or small" options default to small
+	help
+	This option makes top and ps ~20% faster (or 20% less CPU hungry),
+	but code size is slightly bigger.
+
+config BUSYBOX_CONFIG_FEATURE_SHOW_THREADS
+	bool "Support thread display in ps/pstree/top"
+	default BUSYBOX_DEFAULT_FEATURE_SHOW_THREADS
+	depends on BUSYBOX_CONFIG_PS || BUSYBOX_CONFIG_TOP || BUSYBOX_CONFIG_PSTREE
+	help
+	Enables the ps -T option, showing of threads in pstree,
+	and 'h' command in top.
+
+config BUSYBOX_CONFIG_FREE
+	bool "free (3.1 kb)"
+	default BUSYBOX_DEFAULT_FREE
+	help
+	free displays the total amount of free and used physical and swap
+	memory in the system, as well as the buffers used by the kernel.
+	The shared memory column should be ignored; it is obsolete.
+config BUSYBOX_CONFIG_FUSER
+	bool "fuser (7 kb)"
+	default BUSYBOX_DEFAULT_FUSER
+	help
+	fuser lists all PIDs (Process IDs) that currently have a given
+	file open. fuser can also list all PIDs that have a given network
+	(TCP or UDP) port open.
+config BUSYBOX_CONFIG_IOSTAT
+	bool "iostat (7.6 kb)"
+	default BUSYBOX_DEFAULT_IOSTAT
+	help
+	Report CPU and I/O statistics
+config BUSYBOX_CONFIG_KILL
+	bool "kill (3.1 kb)"
+	default BUSYBOX_DEFAULT_KILL
+	help
+	The command kill sends the specified signal to the specified
+	process or process group. If no signal is specified, the TERM
+	signal is sent.
+
+config BUSYBOX_CONFIG_KILLALL
+	bool "killall (5.6 kb)"
+	default BUSYBOX_DEFAULT_KILLALL
+	help
+	killall sends a signal to all processes running any of the
+	specified commands. If no signal name is specified, SIGTERM is
+	sent.
+
+config BUSYBOX_CONFIG_KILLALL5
+	bool "killall5 (5.3 kb)"
+	default BUSYBOX_DEFAULT_KILLALL5
+	help
+	The SystemV killall command. killall5 sends a signal
+	to all processes except kernel threads and the processes
+	in its own session, so it won't kill the shell that is running
+	the script it was called from.
+config BUSYBOX_CONFIG_LSOF
+	bool "lsof (3.4 kb)"
+	default BUSYBOX_DEFAULT_LSOF
+	help
+	Show open files in the format of:
+	PID <TAB> /path/to/executable <TAB> /path/to/opened/file
+config BUSYBOX_CONFIG_MPSTAT
+	bool "mpstat (9.8 kb)"
+	default BUSYBOX_DEFAULT_MPSTAT
+	help
+	Per-processor statistics
+config BUSYBOX_CONFIG_NMETER
+	bool "nmeter (11 kb)"
+	default BUSYBOX_DEFAULT_NMETER
+	help
+	Prints selected system stats continuously, one line per update.
+config BUSYBOX_CONFIG_PGREP
+	bool "pgrep (6.5 kb)"
+	default BUSYBOX_DEFAULT_PGREP
+	help
+	Look for processes by name.
+
+config BUSYBOX_CONFIG_PKILL
+	bool "pkill (7.5 kb)"
+	default BUSYBOX_DEFAULT_PKILL
+	help
+	Send signals to processes by name.
+config BUSYBOX_CONFIG_PIDOF
+	bool "pidof (6.3 kb)"
+	default BUSYBOX_DEFAULT_PIDOF
+	help
+	Pidof finds the process id's (pids) of the named programs. It prints
+	those id's on the standard output.
+
+config BUSYBOX_CONFIG_FEATURE_PIDOF_SINGLE
+	bool "Enable single shot (-s)"
+	default BUSYBOX_DEFAULT_FEATURE_PIDOF_SINGLE
+	depends on BUSYBOX_CONFIG_PIDOF
+	help
+	Support '-s' for returning only the first pid found.
+
+config BUSYBOX_CONFIG_FEATURE_PIDOF_OMIT
+	bool "Enable omitting pids (-o PID)"
+	default BUSYBOX_DEFAULT_FEATURE_PIDOF_OMIT
+	depends on BUSYBOX_CONFIG_PIDOF
+	help
+	Support '-o PID' for omitting the given pid(s) in output.
+	The special pid %PPID can be used to name the parent process
+	of the pidof, in other words the calling shell or shell script.
+config BUSYBOX_CONFIG_PMAP
+	bool "pmap (6 kb)"
+	default BUSYBOX_DEFAULT_PMAP
+	help
+	Display processes' memory mappings.
+config BUSYBOX_CONFIG_POWERTOP
+	bool "powertop (9.6 kb)"
+	default BUSYBOX_DEFAULT_POWERTOP
+	help
+	Analyze power consumption on Intel-based laptops
+
+config BUSYBOX_CONFIG_FEATURE_POWERTOP_INTERACTIVE
+	bool "Accept keyboard commands"
+	default BUSYBOX_DEFAULT_FEATURE_POWERTOP_INTERACTIVE
+	depends on BUSYBOX_CONFIG_POWERTOP
+	help
+	Without this, powertop will only refresh display every 10 seconds.
+	No keyboard commands will work, only ^C to terminate.
+config BUSYBOX_CONFIG_PS
+	bool "ps (11 kb)"
+	default BUSYBOX_DEFAULT_PS
+	help
+	ps gives a snapshot of the current processes.
+
+config BUSYBOX_CONFIG_FEATURE_PS_WIDE
+	bool "Enable wide output (-w)"
+	default BUSYBOX_DEFAULT_FEATURE_PS_WIDE
+	depends on (BUSYBOX_CONFIG_PS || BUSYBOX_CONFIG_MINIPS) && !BUSYBOX_CONFIG_DESKTOP
+	help
+	Support argument 'w' for wide output.
+	If given once, 132 chars are printed, and if given more
+	than once, the length is unlimited.
+
+config BUSYBOX_CONFIG_FEATURE_PS_LONG
+	bool "Enable long output (-l)"
+	default BUSYBOX_DEFAULT_FEATURE_PS_LONG
+	depends on (BUSYBOX_CONFIG_PS || BUSYBOX_CONFIG_MINIPS) && !BUSYBOX_CONFIG_DESKTOP
+	help
+	Support argument 'l' for long output.
+	Adds fields PPID, RSS, START, TIME & TTY
+
+config BUSYBOX_CONFIG_FEATURE_PS_TIME
+	bool "Enable -o time and -o etime specifiers"
+	default BUSYBOX_DEFAULT_FEATURE_PS_TIME
+	depends on (BUSYBOX_CONFIG_PS || BUSYBOX_CONFIG_MINIPS) && BUSYBOX_CONFIG_DESKTOP
+
+config BUSYBOX_CONFIG_FEATURE_PS_UNUSUAL_SYSTEMS
+	bool "Support Linux prior to 2.4.0 and non-ELF systems"
+	default BUSYBOX_DEFAULT_FEATURE_PS_UNUSUAL_SYSTEMS
+	depends on BUSYBOX_CONFIG_FEATURE_PS_TIME
+	help
+	Include support for measuring HZ on old kernels and non-ELF systems
+	(if you are on Linux 2.4.0+ and use ELF, you don't need this)
+
+config BUSYBOX_CONFIG_FEATURE_PS_ADDITIONAL_COLUMNS
+	bool "Enable -o rgroup, -o ruser, -o nice specifiers"
+	default BUSYBOX_DEFAULT_FEATURE_PS_ADDITIONAL_COLUMNS
+	depends on (BUSYBOX_CONFIG_PS || BUSYBOX_CONFIG_MINIPS) && BUSYBOX_CONFIG_DESKTOP
+config BUSYBOX_CONFIG_PSTREE
+	bool "pstree (9.3 kb)"
+	default BUSYBOX_DEFAULT_PSTREE
+	help
+	Display a tree of processes.
+config BUSYBOX_CONFIG_PWDX
+	bool "pwdx (3.7 kb)"
+	default BUSYBOX_DEFAULT_PWDX
+	help
+	Report current working directory of a process
+config BUSYBOX_CONFIG_SMEMCAP
+	bool "smemcap (2.5 kb)"
+	default BUSYBOX_DEFAULT_SMEMCAP
+	help
+	smemcap is a tool for capturing process data for smem,
+	a memory usage statistic tool.
+config BUSYBOX_CONFIG_BB_SYSCTL
+	bool "sysctl (7.4 kb)"
+	default BUSYBOX_DEFAULT_BB_SYSCTL
+	help
+	Configure kernel parameters at runtime.
+config BUSYBOX_CONFIG_TOP
+	bool "top (18 kb)"
+	default BUSYBOX_DEFAULT_TOP
+	help
+	The top program provides a dynamic real-time view of a running
+	system.
+
+config BUSYBOX_CONFIG_FEATURE_TOP_INTERACTIVE
+	bool "Accept keyboard commands"
+	default BUSYBOX_DEFAULT_FEATURE_TOP_INTERACTIVE
+	depends on BUSYBOX_CONFIG_TOP
+	help
+	Without this, top will only refresh display every 5 seconds.
+	No keyboard commands will work, only ^C to terminate.
+
+config BUSYBOX_CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE
+	bool "Show CPU per-process usage percentage"
+	default BUSYBOX_DEFAULT_FEATURE_TOP_CPU_USAGE_PERCENTAGE
+	depends on BUSYBOX_CONFIG_TOP
+	help
+	Make top display CPU usage for each process.
+	This adds about 2k.
+
+config BUSYBOX_CONFIG_FEATURE_TOP_CPU_GLOBAL_PERCENTS
+	bool "Show CPU global usage percentage"
+	default BUSYBOX_DEFAULT_FEATURE_TOP_CPU_GLOBAL_PERCENTS
+	depends on BUSYBOX_CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE
+	help
+	Makes top display "CPU: NN% usr NN% sys..." line.
+	This adds about 0.5k.
+
+config BUSYBOX_CONFIG_FEATURE_TOP_SMP_CPU
+	bool "SMP CPU usage display ('c' key)"
+	default BUSYBOX_DEFAULT_FEATURE_TOP_SMP_CPU
+	depends on BUSYBOX_CONFIG_FEATURE_TOP_CPU_GLOBAL_PERCENTS
+	help
+	Allow 'c' key to switch between individual/cumulative CPU stats
+	This adds about 0.5k.
+
+config BUSYBOX_CONFIG_FEATURE_TOP_DECIMALS
+	bool "Show 1/10th of a percent in CPU/mem statistics"
+	default BUSYBOX_DEFAULT_FEATURE_TOP_DECIMALS
+	depends on BUSYBOX_CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE
+	help
+	Show 1/10th of a percent in CPU/mem statistics.
+	This adds about 0.3k.
+
+config BUSYBOX_CONFIG_FEATURE_TOP_SMP_PROCESS
+	bool "Show CPU process runs on ('j' field)"
+	default BUSYBOX_DEFAULT_FEATURE_TOP_SMP_PROCESS
+	depends on BUSYBOX_CONFIG_TOP
+	help
+	Show CPU where process was last found running on.
+	This is the 'j' field.
+
+config BUSYBOX_CONFIG_FEATURE_TOPMEM
+	bool "Topmem command ('s' key)"
+	default BUSYBOX_DEFAULT_FEATURE_TOPMEM
+	depends on BUSYBOX_CONFIG_TOP
+	help
+	Enable 's' in top (gives lots of memory info).
+config BUSYBOX_CONFIG_UPTIME
+	bool "uptime (3.7 kb)"
+	default BUSYBOX_DEFAULT_UPTIME
+	help
+	uptime gives a one line display of the current time, how long
+	the system has been running, how many users are currently logged
+	on, and the system load averages for the past 1, 5, and 15 minutes.
+
+config BUSYBOX_CONFIG_FEATURE_UPTIME_UTMP_SUPPORT
+	bool "Show the number of users"
+	default BUSYBOX_DEFAULT_FEATURE_UPTIME_UTMP_SUPPORT
+	depends on BUSYBOX_CONFIG_UPTIME && BUSYBOX_CONFIG_FEATURE_UTMP
+	help
+	Display the number of users currently logged on.
+config BUSYBOX_CONFIG_WATCH
+	bool "watch (4.4 kb)"
+	default BUSYBOX_DEFAULT_WATCH
+	help
+	watch is used to execute a program periodically, showing
+	output to the screen.
+
+endmenu
diff --git a/package/utils/busybox/config/runit/Config.in b/package/utils/busybox/config/runit/Config.in
new file mode 100644
index 0000000..2c701f2
--- /dev/null
+++ b/package/utils/busybox/config/runit/Config.in
@@ -0,0 +1,98 @@
+# DO NOT EDIT. This file is generated from Config.src
+#
+# For a description of the syntax of this configuration file,
+# see docs/Kconfig-language.txt.
+#
+
+menu "Runit Utilities"
+
+config BUSYBOX_CONFIG_CHPST
+	bool "chpst (9 kb)"
+	default BUSYBOX_DEFAULT_CHPST
+	help
+	chpst changes the process state according to the given options, and
+	execs specified program.
+
+config BUSYBOX_CONFIG_SETUIDGID
+	bool "setuidgid (4 kb)"
+	default BUSYBOX_DEFAULT_SETUIDGID
+	help
+	Sets soft resource limits as specified by options
+
+config BUSYBOX_CONFIG_ENVUIDGID
+	bool "envuidgid (3.9 kb)"
+	default BUSYBOX_DEFAULT_ENVUIDGID
+	help
+	Sets $UID to account's uid and $GID to account's gid
+
+config BUSYBOX_CONFIG_ENVDIR
+	bool "envdir (2.5 kb)"
+	default BUSYBOX_DEFAULT_ENVDIR
+	help
+	Sets various environment variables as specified by files
+	in the given directory
+
+config BUSYBOX_CONFIG_SOFTLIMIT
+	bool "softlimit (4.5 kb)"
+	default BUSYBOX_DEFAULT_SOFTLIMIT
+	help
+	Sets soft resource limits as specified by options
+config BUSYBOX_CONFIG_RUNSV
+	bool "runsv (7.8 kb)"
+	default BUSYBOX_DEFAULT_RUNSV
+	help
+	runsv starts and monitors a service and optionally an appendant log
+	service.
+config BUSYBOX_CONFIG_RUNSVDIR
+	bool "runsvdir (6.3 kb)"
+	default BUSYBOX_DEFAULT_RUNSVDIR
+	help
+	runsvdir starts a runsv process for each subdirectory, or symlink to
+	a directory, in the services directory dir, up to a limit of 1000
+	subdirectories, and restarts a runsv process if it terminates.
+
+config BUSYBOX_CONFIG_FEATURE_RUNSVDIR_LOG
+	bool "Enable scrolling argument log"
+	depends on BUSYBOX_CONFIG_RUNSVDIR
+	default BUSYBOX_DEFAULT_FEATURE_RUNSVDIR_LOG
+	help
+	Enable feature where second parameter of runsvdir holds last error
+	message (viewable via top/ps). Otherwise (feature is off
+	or no parameter), error messages go to stderr only.
+config BUSYBOX_CONFIG_SV
+	bool "sv (8.5 kb)"
+	default BUSYBOX_DEFAULT_SV
+	help
+	sv reports the current status and controls the state of services
+	monitored by the runsv supervisor.
+
+config BUSYBOX_CONFIG_SV_DEFAULT_SERVICE_DIR
+	string "Default directory for services"
+	default BUSYBOX_DEFAULT_SV_DEFAULT_SERVICE_DIR
+	depends on BUSYBOX_CONFIG_SV || BUSYBOX_CONFIG_SVC || BUSYBOX_CONFIG_SVOK
+	help
+	Default directory for services.
+	Defaults to "/var/service"
+
+config BUSYBOX_CONFIG_SVC
+	bool "svc (8.4 kb)"
+	default BUSYBOX_DEFAULT_SVC
+	help
+	svc controls the state of services monitored by the runsv supervisor.
+	It is compatible with daemontools command with the same name.
+
+config BUSYBOX_CONFIG_SVOK
+	bool "svok (1.5 kb)"
+	default BUSYBOX_DEFAULT_SVOK
+	help
+	svok checks whether runsv supervisor is running.
+	It is compatible with daemontools command with the same name.
+config BUSYBOX_CONFIG_SVLOGD
+	bool "svlogd (16 kb)"
+	default BUSYBOX_DEFAULT_SVLOGD
+	help
+	svlogd continuously reads log data from its standard input, optionally
+	filters log messages, and writes the data to one or more automatically
+	rotated logs.
+
+endmenu
diff --git a/package/utils/busybox/config/selinux/Config.in b/package/utils/busybox/config/selinux/Config.in
new file mode 100644
index 0000000..de67a72
--- /dev/null
+++ b/package/utils/busybox/config/selinux/Config.in
@@ -0,0 +1,99 @@
+# DO NOT EDIT. This file is generated from Config.src
+#
+# For a description of the syntax of this configuration file,
+# see docs/Kconfig-language.txt.
+#
+
+menu "SELinux Utilities"
+	depends on BUSYBOX_CONFIG_SELINUX
+
+config BUSYBOX_CONFIG_CHCON
+	bool "chcon (8.9 kb)"
+	default BUSYBOX_DEFAULT_CHCON
+	depends on BUSYBOX_CONFIG_SELINUX
+	help
+	Enable support to change the security context of file.
+config BUSYBOX_CONFIG_GETENFORCE
+	bool "getenforce (1.7 kb)"
+	default BUSYBOX_DEFAULT_GETENFORCE
+	depends on BUSYBOX_CONFIG_SELINUX
+	help
+	Enable support to get the current mode of SELinux.
+config BUSYBOX_CONFIG_GETSEBOOL
+	bool "getsebool (5.5 kb)"
+	default BUSYBOX_DEFAULT_GETSEBOOL
+	depends on BUSYBOX_CONFIG_SELINUX
+	help
+	Enable support to get SELinux boolean values.
+config BUSYBOX_CONFIG_LOAD_POLICY
+	bool "load_policy (1.6 kb)"
+	default BUSYBOX_DEFAULT_LOAD_POLICY
+	depends on BUSYBOX_CONFIG_SELINUX
+	help
+	Enable support to load SELinux policy.
+config BUSYBOX_CONFIG_MATCHPATHCON
+	bool "matchpathcon (6.1 kb)"
+	default BUSYBOX_DEFAULT_MATCHPATHCON
+	depends on BUSYBOX_CONFIG_SELINUX
+	help
+	Enable support to get default security context of the
+	specified path from the file contexts configuration.
+config BUSYBOX_CONFIG_RUNCON
+	bool "runcon (6.6 kb)"
+	default BUSYBOX_DEFAULT_RUNCON
+	depends on BUSYBOX_CONFIG_SELINUX
+	help
+	Enable support to run command in specified security context.
+config BUSYBOX_CONFIG_SELINUXENABLED
+	bool "selinuxenabled (321 bytes)"
+	default BUSYBOX_DEFAULT_SELINUXENABLED
+	depends on BUSYBOX_CONFIG_SELINUX
+	help
+	Enable support for this command to be used within shell scripts
+	to determine if selinux is enabled.
+config BUSYBOX_CONFIG_SESTATUS
+	bool "sestatus (12 kb)"
+	default BUSYBOX_DEFAULT_SESTATUS
+	depends on BUSYBOX_CONFIG_SELINUX
+	help
+	Displays the status of SELinux.
+config BUSYBOX_CONFIG_SETENFORCE
+	bool "setenforce (2.1 kb)"
+	default BUSYBOX_DEFAULT_SETENFORCE
+	depends on BUSYBOX_CONFIG_SELINUX
+	help
+	Enable support to modify the mode SELinux is running in.
+config BUSYBOX_CONFIG_SETFILES
+	bool "setfiles (13 kb)"
+	default BUSYBOX_DEFAULT_SETFILES
+	depends on BUSYBOX_CONFIG_SELINUX
+	help
+	Enable support to modify to relabel files.
+	Notice: If you built libselinux with -D_FILE_OFFSET_BITS=64,
+	(It is default in libselinux's Makefile), you _must_ enable
+	CONFIG_LFS.
+
+config BUSYBOX_CONFIG_FEATURE_SETFILES_CHECK_OPTION
+	bool "Enable check option"
+	default BUSYBOX_DEFAULT_FEATURE_SETFILES_CHECK_OPTION
+	depends on BUSYBOX_CONFIG_SETFILES
+	help
+	Support "-c" option (check the validity of the contexts against
+	the specified binary policy) for setfiles. Requires libsepol.
+
+config BUSYBOX_CONFIG_RESTORECON
+	bool "restorecon (12 kb)"
+	default BUSYBOX_DEFAULT_RESTORECON
+	depends on BUSYBOX_CONFIG_SELINUX
+	help
+	Enable support to relabel files. The feature is almost
+	the same as setfiles, but usage is a little different.
+config BUSYBOX_CONFIG_SETSEBOOL
+	bool "setsebool (1.7 kb)"
+	default BUSYBOX_DEFAULT_SETSEBOOL
+	depends on BUSYBOX_CONFIG_SELINUX
+	help
+	Enable support for change boolean.
+	semanage and -P option is not supported yet.
+
+endmenu
diff --git a/package/utils/busybox/config/shell/Config.in b/package/utils/busybox/config/shell/Config.in
new file mode 100644
index 0000000..a68e911
--- /dev/null
+++ b/package/utils/busybox/config/shell/Config.in
@@ -0,0 +1,608 @@
+# DO NOT EDIT. This file is generated from Config.src
+#
+# For a description of the syntax of this configuration file,
+# see docs/Kconfig-language.txt.
+#
+
+menu "Shells"
+
+
+choice
+	prompt "Choose which shell is aliased to 'sh' name"
+	default BUSYBOX_CONFIG_SH_IS_ASH
+	help
+	Choose which shell you want to be executed by 'sh' alias.
+	The ash shell is the most bash compatible and full featured one.
+
+# note: cannot use "select ASH" here, it breaks "make allnoconfig"
+config BUSYBOX_CONFIG_SH_IS_ASH
+	depends on !BUSYBOX_CONFIG_NOMMU
+	bool "ash"
+	select BUSYBOX_CONFIG_SHELL_ASH
+	help
+	Choose ash to be the shell executed by 'sh' name.
+	The ash code will be built into busybox. If you don't select
+	"ash" choice (CONFIG_ASH), this shell may only be invoked by
+	the name 'sh' (and not 'ash').
+
+config BUSYBOX_CONFIG_SH_IS_HUSH
+	bool "hush"
+	select BUSYBOX_CONFIG_SHELL_HUSH
+	help
+	Choose hush to be the shell executed by 'sh' name.
+	The hush code will be built into busybox. If you don't select
+	"hush" choice (CONFIG_HUSH), this shell may only be invoked by
+	the name 'sh' (and not 'hush').
+
+config BUSYBOX_CONFIG_SH_IS_NONE
+	bool "none"
+
+endchoice
+
+choice
+	prompt "Choose which shell is aliased to 'bash' name"
+	default BUSYBOX_CONFIG_BASH_IS_NONE
+	help
+	Choose which shell you want to be executed by 'bash' alias.
+	The ash shell is the most bash compatible and full featured one,
+	although compatibility is far from being complete.
+
+	Note that selecting this option does not switch on any bash
+	compatibility code. It merely makes it possible to install
+	/bin/bash (sym)link and run scripts which start with
+	#!/bin/bash line.
+
+	Many systems use it in scripts which use bash-specific features,
+	even simple ones like $RANDOM. Without this option, busybox
+	can't be used for running them because it won't recongnize
+	"bash" as a supported applet name.
+
+config BUSYBOX_CONFIG_BASH_IS_ASH
+	depends on !BUSYBOX_CONFIG_NOMMU
+	bool "ash"
+	select BUSYBOX_CONFIG_SHELL_ASH
+	help
+	Choose ash to be the shell executed by 'bash' name.
+	The ash code will be built into busybox. If you don't select
+	"ash" choice (CONFIG_ASH), this shell may only be invoked by
+	the name 'bash' (and not 'ash').
+
+config BUSYBOX_CONFIG_BASH_IS_HUSH
+	bool "hush"
+	select BUSYBOX_CONFIG_SHELL_HUSH
+	help
+	Choose hush to be the shell executed by 'bash' name.
+	The hush code will be built into busybox. If you don't select
+	"hush" choice (CONFIG_HUSH), this shell may only be invoked by
+	the name 'bash' (and not 'hush').
+
+config BUSYBOX_CONFIG_BASH_IS_NONE
+	bool "none"
+
+endchoice
+
+
+config BUSYBOX_CONFIG_SHELL_ASH
+	bool #hidden option
+	depends on !BUSYBOX_CONFIG_NOMMU
+
+config BUSYBOX_CONFIG_ASH
+	bool "ash (78 kb)"
+	default BUSYBOX_DEFAULT_ASH
+	depends on !BUSYBOX_CONFIG_NOMMU
+	select BUSYBOX_CONFIG_SHELL_ASH
+	help
+	The most complete and most pedantically correct shell included with
+	busybox. This shell is actually a derivative of the Debian 'dash'
+	shell (by Herbert Xu), which was created by porting the 'ash' shell
+	(written by Kenneth Almquist) from NetBSD.
+
+# ash options
+# note: Don't remove !NOMMU part in the next line; it would break
+# menuconfig's indenting.
+if !NOMMU && (BUSYBOX_CONFIG_SHELL_ASH || BUSYBOX_CONFIG_ASH || BUSYBOX_CONFIG_SH_IS_ASH || BUSYBOX_CONFIG_BASH_IS_ASH)
+
+config BUSYBOX_CONFIG_ASH_OPTIMIZE_FOR_SIZE
+	bool "Optimize for size instead of speed"
+	default BUSYBOX_DEFAULT_ASH_OPTIMIZE_FOR_SIZE
+	depends on BUSYBOX_CONFIG_SHELL_ASH
+
+config BUSYBOX_CONFIG_ASH_INTERNAL_GLOB
+	bool "Use internal glob() implementation"
+	default BUSYBOX_DEFAULT_ASH_INTERNAL_GLOB	# Y is bigger, but because of uclibc glob() bug, let Y be default for now
+	depends on BUSYBOX_CONFIG_SHELL_ASH
+	help
+	Do not use glob() function from libc, use internal implementation.
+	Use this if you are getting "glob.h: No such file or directory"
+	or similar build errors.
+	Note that as of now (2017-01), uclibc and musl glob() both have bugs
+	which would break ash if you select N here.
+
+config BUSYBOX_CONFIG_ASH_BASH_COMPAT
+	bool "bash-compatible extensions"
+	default BUSYBOX_DEFAULT_ASH_BASH_COMPAT
+	depends on BUSYBOX_CONFIG_SHELL_ASH
+
+config BUSYBOX_CONFIG_ASH_BASH_SOURCE_CURDIR
+	bool "'source' and '.' builtins search current directory after $PATH"
+	default BUSYBOX_DEFAULT_ASH_BASH_SOURCE_CURDIR   # do not encourage non-standard behavior
+	depends on BUSYBOX_CONFIG_ASH_BASH_COMPAT
+	help
+	This is not compliant with standards. Avoid if possible.
+
+config BUSYBOX_CONFIG_ASH_BASH_NOT_FOUND_HOOK
+	bool "command_not_found_handle hook support"
+	default BUSYBOX_DEFAULT_ASH_BASH_NOT_FOUND_HOOK
+	depends on BUSYBOX_CONFIG_ASH_BASH_COMPAT
+	help
+	Enable support for the 'command_not_found_handle' hook function,
+	from GNU bash, which allows for alternative command not found
+	handling.
+
+config BUSYBOX_CONFIG_ASH_JOB_CONTROL
+	bool "Job control"
+	default BUSYBOX_DEFAULT_ASH_JOB_CONTROL
+	depends on BUSYBOX_CONFIG_SHELL_ASH
+
+config BUSYBOX_CONFIG_ASH_ALIAS
+	bool "Alias support"
+	default BUSYBOX_DEFAULT_ASH_ALIAS
+	depends on BUSYBOX_CONFIG_SHELL_ASH
+
+config BUSYBOX_CONFIG_ASH_RANDOM_SUPPORT
+	bool "Pseudorandom generator and $RANDOM variable"
+	default BUSYBOX_DEFAULT_ASH_RANDOM_SUPPORT
+	depends on BUSYBOX_CONFIG_SHELL_ASH
+	help
+	Enable pseudorandom generator and dynamic variable "$RANDOM".
+	Each read of "$RANDOM" will generate a new pseudorandom value.
+	You can reset the generator by using a specified start value.
+	After "unset RANDOM" the generator will switch off and this
+	variable will no longer have special treatment.
+
+config BUSYBOX_CONFIG_ASH_EXPAND_PRMT
+	bool "Expand prompt string"
+	default BUSYBOX_DEFAULT_ASH_EXPAND_PRMT
+	depends on BUSYBOX_CONFIG_SHELL_ASH
+	help
+	$PS# may contain volatile content, such as backquote commands.
+	This option recreates the prompt string from the environment
+	variable each time it is displayed.
+
+config BUSYBOX_CONFIG_ASH_IDLE_TIMEOUT
+	bool "Idle timeout variable $TMOUT"
+	default BUSYBOX_DEFAULT_ASH_IDLE_TIMEOUT
+	depends on BUSYBOX_CONFIG_SHELL_ASH
+	help
+	Enable bash-like auto-logout after $TMOUT seconds of idle time.
+
+config BUSYBOX_CONFIG_ASH_MAIL
+	bool "Check for new mail in interactive shell"
+	default BUSYBOX_DEFAULT_ASH_MAIL
+	depends on BUSYBOX_CONFIG_SHELL_ASH
+	help
+	Enable "check for new mail" function:
+	if set, $MAIL file and $MAILPATH list of files
+	are checked for mtime changes, and "you have mail"
+	message is printed if change is detected.
+
+config BUSYBOX_CONFIG_ASH_ECHO
+	bool "echo builtin"
+	default BUSYBOX_DEFAULT_ASH_ECHO
+	depends on BUSYBOX_CONFIG_SHELL_ASH
+
+config BUSYBOX_CONFIG_ASH_PRINTF
+	bool "printf builtin"
+	default BUSYBOX_DEFAULT_ASH_PRINTF
+	depends on BUSYBOX_CONFIG_SHELL_ASH
+
+config BUSYBOX_CONFIG_ASH_TEST
+	bool "test builtin"
+	default BUSYBOX_DEFAULT_ASH_TEST
+	depends on BUSYBOX_CONFIG_SHELL_ASH
+
+config BUSYBOX_CONFIG_ASH_SLEEP
+	bool "sleep builtin"
+	default BUSYBOX_DEFAULT_ASH_SLEEP
+	depends on BUSYBOX_CONFIG_SHELL_ASH
+
+config BUSYBOX_CONFIG_ASH_HELP
+	bool "help builtin"
+	default BUSYBOX_DEFAULT_ASH_HELP
+	depends on BUSYBOX_CONFIG_SHELL_ASH
+
+config BUSYBOX_CONFIG_ASH_GETOPTS
+	bool "getopts builtin"
+	default BUSYBOX_DEFAULT_ASH_GETOPTS
+	depends on BUSYBOX_CONFIG_SHELL_ASH
+
+config BUSYBOX_CONFIG_ASH_CMDCMD
+	bool "command builtin"
+	default BUSYBOX_DEFAULT_ASH_CMDCMD
+	depends on BUSYBOX_CONFIG_SHELL_ASH
+	help
+	Enable support for the 'command' builtin, which allows
+	you to run the specified command or builtin,
+	even when there is a function with the same name.
+
+endif # ash options
+config BUSYBOX_CONFIG_CTTYHACK
+	bool "cttyhack (2.4 kb)"
+	default BUSYBOX_DEFAULT_CTTYHACK
+	help
+	One common problem reported on the mailing list is the "can't
+	access tty; job control turned off" error message, which typically
+	appears when one tries to use a shell with stdin/stdout on
+	/dev/console.
+	This device is special - it cannot be a controlling tty.
+
+	The proper solution is to use the correct device instead of
+	/dev/console.
+
+	cttyhack provides a "quick and dirty" solution to this problem.
+	It analyzes stdin with various ioctls, trying to determine whether
+	it is a /dev/ttyN or /dev/ttySN (virtual terminal or serial line).
+	On Linux it also checks sysfs for a pointer to the active console.
+	If cttyhack is able to find the real console device, it closes
+	stdin/out/err and reopens that device.
+	Then it executes the given program. Opening the device will make
+	that device a controlling tty. This may require cttyhack
+	to be a session leader.
+
+	Example for /etc/inittab (for busybox init):
+
+	::respawn:/bin/cttyhack /bin/sh
+
+	Starting an interactive shell from boot shell script:
+
+	setsid cttyhack sh
+
+	Giving controlling tty to shell running with PID 1:
+
+	# exec cttyhack sh
+
+	Without cttyhack, you need to know exact tty name,
+	and do something like this:
+
+	# exec setsid sh -c 'exec sh </dev/tty1 >/dev/tty1 2>&1'
+
+	Starting getty on a controlling tty from a shell script:
+
+	# getty 115200 $(cttyhack)
+config BUSYBOX_CONFIG_HUSH
+	bool "hush (68 kb)"
+	default BUSYBOX_DEFAULT_HUSH
+	select BUSYBOX_CONFIG_SHELL_HUSH
+	help
+	hush is a small shell. It handles the normal flow control
+	constructs such as if/then/elif/else/fi, for/in/do/done, while loops,
+	case/esac. Redirections, here documents, $((arithmetic))
+	and functions are supported.
+
+	It will compile and work on no-mmu systems.
+
+	It does not handle select, aliases, tilde expansion,
+	&>file and >&file redirection of stdout+stderr.
+
+config BUSYBOX_CONFIG_SHELL_HUSH
+	bool "Internal shell for embedded script support"
+	default BUSYBOX_DEFAULT_SHELL_HUSH
+
+# hush options
+# It's only needed to get "nice" menuconfig indenting.
+if SHELL_HUSH || BUSYBOX_CONFIG_HUSH || BUSYBOX_CONFIG_SH_IS_HUSH || BUSYBOX_CONFIG_BASH_IS_HUSH
+
+config BUSYBOX_CONFIG_HUSH_BASH_COMPAT
+	bool "bash-compatible extensions"
+	default BUSYBOX_DEFAULT_HUSH_BASH_COMPAT
+	depends on BUSYBOX_CONFIG_SHELL_HUSH
+
+config BUSYBOX_CONFIG_HUSH_BRACE_EXPANSION
+	bool "Brace expansion"
+	default BUSYBOX_DEFAULT_HUSH_BRACE_EXPANSION
+	depends on BUSYBOX_CONFIG_HUSH_BASH_COMPAT
+	help
+	Enable {abc,def} extension.
+
+config BUSYBOX_CONFIG_HUSH_BASH_SOURCE_CURDIR
+	bool "'source' and '.' builtins search current directory after $PATH"
+	default BUSYBOX_DEFAULT_HUSH_BASH_SOURCE_CURDIR   # do not encourage non-standard behavior
+	depends on BUSYBOX_CONFIG_HUSH_BASH_COMPAT
+	help
+	This is not compliant with standards. Avoid if possible.
+
+config BUSYBOX_CONFIG_HUSH_LINENO_VAR
+	bool "$LINENO variable (bashism)"
+	default BUSYBOX_DEFAULT_HUSH_LINENO_VAR
+	depends on BUSYBOX_CONFIG_SHELL_HUSH
+
+config BUSYBOX_CONFIG_HUSH_INTERACTIVE
+	bool "Interactive mode"
+	default BUSYBOX_DEFAULT_HUSH_INTERACTIVE
+	depends on BUSYBOX_CONFIG_SHELL_HUSH
+	help
+	Enable interactive mode (prompt and command editing).
+	Without this, hush simply reads and executes commands
+	from stdin just like a shell script from a file.
+	No prompt, no PS1/PS2 magic shell variables.
+
+config BUSYBOX_CONFIG_HUSH_SAVEHISTORY
+	bool "Save command history to .hush_history"
+	default BUSYBOX_DEFAULT_HUSH_SAVEHISTORY
+	depends on BUSYBOX_CONFIG_HUSH_INTERACTIVE && BUSYBOX_CONFIG_FEATURE_EDITING_SAVEHISTORY
+
+config BUSYBOX_CONFIG_HUSH_JOB
+	bool "Job control"
+	default BUSYBOX_DEFAULT_HUSH_JOB
+	depends on BUSYBOX_CONFIG_HUSH_INTERACTIVE
+	help
+	Enable job control: Ctrl-Z backgrounds, Ctrl-C interrupts current
+	command (not entire shell), fg/bg builtins work. Without this option,
+	"cmd &" still works by simply spawning a process and immediately
+	prompting for next command (or executing next command in a script),
+	but no separate process group is formed.
+
+config BUSYBOX_CONFIG_HUSH_TICK
+	bool "Support command substitution"
+	default BUSYBOX_DEFAULT_HUSH_TICK
+	depends on BUSYBOX_CONFIG_SHELL_HUSH
+	help
+	Enable `command` and $(command).
+
+config BUSYBOX_CONFIG_HUSH_IF
+	bool "Support if/then/elif/else/fi"
+	default BUSYBOX_DEFAULT_HUSH_IF
+	depends on BUSYBOX_CONFIG_SHELL_HUSH
+
+config BUSYBOX_CONFIG_HUSH_LOOPS
+	bool "Support for, while and until loops"
+	default BUSYBOX_DEFAULT_HUSH_LOOPS
+	depends on BUSYBOX_CONFIG_SHELL_HUSH
+
+config BUSYBOX_CONFIG_HUSH_CASE
+	bool "Support case ... esac statement"
+	default BUSYBOX_DEFAULT_HUSH_CASE
+	depends on BUSYBOX_CONFIG_SHELL_HUSH
+	help
+	Enable case ... esac statement. +400 bytes.
+
+config BUSYBOX_CONFIG_HUSH_FUNCTIONS
+	bool "Support funcname() { commands; } syntax"
+	default BUSYBOX_DEFAULT_HUSH_FUNCTIONS
+	depends on BUSYBOX_CONFIG_SHELL_HUSH
+	help
+	Enable support for shell functions. +800 bytes.
+
+config BUSYBOX_CONFIG_HUSH_LOCAL
+	bool "local builtin"
+	default BUSYBOX_DEFAULT_HUSH_LOCAL
+	depends on BUSYBOX_CONFIG_HUSH_FUNCTIONS
+	help
+	Enable support for local variables in functions.
+
+config BUSYBOX_CONFIG_HUSH_RANDOM_SUPPORT
+	bool "Pseudorandom generator and $RANDOM variable"
+	default BUSYBOX_DEFAULT_HUSH_RANDOM_SUPPORT
+	depends on BUSYBOX_CONFIG_SHELL_HUSH
+	help
+	Enable pseudorandom generator and dynamic variable "$RANDOM".
+	Each read of "$RANDOM" will generate a new pseudorandom value.
+
+config BUSYBOX_CONFIG_HUSH_MODE_X
+	bool "Support 'hush -x' option and 'set -x' command"
+	default BUSYBOX_DEFAULT_HUSH_MODE_X
+	depends on BUSYBOX_CONFIG_SHELL_HUSH
+	help
+	This instructs hush to print commands before execution.
+	Adds ~300 bytes.
+
+config BUSYBOX_CONFIG_HUSH_ECHO
+	bool "echo builtin"
+	default BUSYBOX_DEFAULT_HUSH_ECHO
+	depends on BUSYBOX_CONFIG_SHELL_HUSH
+
+config BUSYBOX_CONFIG_HUSH_PRINTF
+	bool "printf builtin"
+	default BUSYBOX_DEFAULT_HUSH_PRINTF
+	depends on BUSYBOX_CONFIG_SHELL_HUSH
+
+config BUSYBOX_CONFIG_HUSH_TEST
+	bool "test builtin"
+	default BUSYBOX_DEFAULT_HUSH_TEST
+	depends on BUSYBOX_CONFIG_SHELL_HUSH
+
+config BUSYBOX_CONFIG_HUSH_HELP
+	bool "help builtin"
+	default BUSYBOX_DEFAULT_HUSH_HELP
+	depends on BUSYBOX_CONFIG_SHELL_HUSH
+
+config BUSYBOX_CONFIG_HUSH_EXPORT
+	bool "export builtin"
+	default BUSYBOX_DEFAULT_HUSH_EXPORT
+	depends on BUSYBOX_CONFIG_SHELL_HUSH
+
+config BUSYBOX_CONFIG_HUSH_EXPORT_N
+	bool "Support 'export -n' option"
+	default BUSYBOX_DEFAULT_HUSH_EXPORT_N
+	depends on BUSYBOX_CONFIG_HUSH_EXPORT
+	help
+	export -n unexports variables. It is a bash extension.
+
+config BUSYBOX_CONFIG_HUSH_READONLY
+	bool "readonly builtin"
+	default BUSYBOX_DEFAULT_HUSH_READONLY
+	depends on BUSYBOX_CONFIG_SHELL_HUSH
+	help
+	Enable support for read-only variables.
+
+config BUSYBOX_CONFIG_HUSH_KILL
+	bool "kill builtin (supports kill %jobspec)"
+	default BUSYBOX_DEFAULT_HUSH_KILL
+	depends on BUSYBOX_CONFIG_SHELL_HUSH
+
+config BUSYBOX_CONFIG_HUSH_WAIT
+	bool "wait builtin"
+	default BUSYBOX_DEFAULT_HUSH_WAIT
+	depends on BUSYBOX_CONFIG_SHELL_HUSH
+
+config BUSYBOX_CONFIG_HUSH_COMMAND
+	bool "command builtin"
+	default BUSYBOX_DEFAULT_HUSH_COMMAND
+	depends on BUSYBOX_CONFIG_SHELL_HUSH
+
+config BUSYBOX_CONFIG_HUSH_TRAP
+	bool "trap builtin"
+	default BUSYBOX_DEFAULT_HUSH_TRAP
+	depends on BUSYBOX_CONFIG_SHELL_HUSH
+
+config BUSYBOX_CONFIG_HUSH_TYPE
+	bool "type builtin"
+	default BUSYBOX_DEFAULT_HUSH_TYPE
+	depends on BUSYBOX_CONFIG_SHELL_HUSH
+
+config BUSYBOX_CONFIG_HUSH_TIMES
+	bool "times builtin"
+	default BUSYBOX_DEFAULT_HUSH_TIMES
+	depends on BUSYBOX_CONFIG_SHELL_HUSH
+
+config BUSYBOX_CONFIG_HUSH_READ
+	bool "read builtin"
+	default BUSYBOX_DEFAULT_HUSH_READ
+	depends on BUSYBOX_CONFIG_SHELL_HUSH
+
+config BUSYBOX_CONFIG_HUSH_SET
+	bool "set builtin"
+	default BUSYBOX_DEFAULT_HUSH_SET
+	depends on BUSYBOX_CONFIG_SHELL_HUSH
+
+config BUSYBOX_CONFIG_HUSH_UNSET
+	bool "unset builtin"
+	default BUSYBOX_DEFAULT_HUSH_UNSET
+	depends on BUSYBOX_CONFIG_SHELL_HUSH
+
+config BUSYBOX_CONFIG_HUSH_ULIMIT
+	bool "ulimit builtin"
+	default BUSYBOX_DEFAULT_HUSH_ULIMIT
+	depends on BUSYBOX_CONFIG_SHELL_HUSH
+
+config BUSYBOX_CONFIG_HUSH_UMASK
+	bool "umask builtin"
+	default BUSYBOX_DEFAULT_HUSH_UMASK
+	depends on BUSYBOX_CONFIG_SHELL_HUSH
+
+config BUSYBOX_CONFIG_HUSH_GETOPTS
+	bool "getopts builtin"
+	default BUSYBOX_DEFAULT_HUSH_GETOPTS
+	depends on BUSYBOX_CONFIG_SHELL_HUSH
+
+config BUSYBOX_CONFIG_HUSH_MEMLEAK
+	bool "memleak builtin (debugging)"
+	default BUSYBOX_DEFAULT_HUSH_MEMLEAK
+	depends on BUSYBOX_CONFIG_SHELL_HUSH
+
+endif # hush options
+
+
+comment "Options common to all shells"
+if BUSYBOX_CONFIG_SHELL_ASH || BUSYBOX_CONFIG_SHELL_HUSH
+
+config BUSYBOX_CONFIG_FEATURE_SH_MATH
+	bool "POSIX math support"
+	default BUSYBOX_DEFAULT_FEATURE_SH_MATH
+	depends on BUSYBOX_CONFIG_SHELL_ASH || BUSYBOX_CONFIG_SHELL_HUSH
+	help
+	Enable math support in the shell via $((...)) syntax.
+
+config BUSYBOX_CONFIG_FEATURE_SH_MATH_64
+	bool "Extend POSIX math support to 64 bit"
+	default BUSYBOX_DEFAULT_FEATURE_SH_MATH_64
+	depends on BUSYBOX_CONFIG_FEATURE_SH_MATH
+	help
+	Enable 64-bit math support in the shell. This will make the shell
+	slightly larger, but will allow computation with very large numbers.
+	This is not in POSIX, so do not rely on this in portable code.
+
+config BUSYBOX_CONFIG_FEATURE_SH_MATH_BASE
+	bool "Support BASE#nnnn literals"
+	default BUSYBOX_DEFAULT_FEATURE_SH_MATH_BASE
+	depends on BUSYBOX_CONFIG_FEATURE_SH_MATH
+
+config BUSYBOX_CONFIG_FEATURE_SH_EXTRA_QUIET
+	bool "Hide message on interactive shell startup"
+	default BUSYBOX_DEFAULT_FEATURE_SH_EXTRA_QUIET
+	depends on BUSYBOX_CONFIG_SHELL_ASH || BUSYBOX_CONFIG_SHELL_HUSH
+	help
+	Remove the busybox introduction when starting a shell.
+
+config BUSYBOX_CONFIG_FEATURE_SH_STANDALONE
+	bool "Standalone shell"
+	default BUSYBOX_DEFAULT_FEATURE_SH_STANDALONE
+	depends on BUSYBOX_CONFIG_SHELL_ASH || BUSYBOX_CONFIG_SHELL_HUSH
+	help
+	This option causes busybox shells to use busybox applets
+	in preference to executables in the PATH whenever possible. For
+	example, entering the command 'ifconfig' into the shell would cause
+	busybox to use the ifconfig busybox applet. Specifying the fully
+	qualified executable name, such as '/sbin/ifconfig' will still
+	execute the /sbin/ifconfig executable on the filesystem. This option
+	is generally used when creating a statically linked version of busybox
+	for use as a rescue shell, in the event that you screw up your system.
+
+	This is implemented by re-execing /proc/self/exe (typically)
+	with right parameters.
+
+	However, there are drawbacks: it is problematic in chroot jails
+	without mounted /proc, and ps/top may show command name as 'exe'
+	for applets started this way.
+
+config BUSYBOX_CONFIG_FEATURE_SH_NOFORK
+	bool "Run 'nofork' applets directly"
+	default BUSYBOX_DEFAULT_FEATURE_SH_NOFORK
+	depends on BUSYBOX_CONFIG_SHELL_ASH || BUSYBOX_CONFIG_SHELL_HUSH
+	help
+	This option causes busybox shells to not execute typical
+	fork/exec/wait sequence, but call <applet>_main directly,
+	if possible. (Sometimes it is not possible: for example,
+	this is not possible in pipes).
+
+	This will be done only for some applets (those which are marked
+	NOFORK in include/applets.h).
+
+	This may significantly speed up some shell scripts.
+
+	This feature is relatively new. Use with care. Report bugs
+	to project mailing list.
+
+config BUSYBOX_CONFIG_FEATURE_SH_READ_FRAC
+	bool "read -t N.NNN support (+110 bytes)"
+	default BUSYBOX_DEFAULT_FEATURE_SH_READ_FRAC
+	depends on BUSYBOX_CONFIG_SHELL_ASH || BUSYBOX_CONFIG_SHELL_HUSH
+	help
+	Enable support for fractional second timeout in read builtin.
+
+config BUSYBOX_CONFIG_FEATURE_SH_HISTFILESIZE
+	bool "Use $HISTFILESIZE"
+	default BUSYBOX_DEFAULT_FEATURE_SH_HISTFILESIZE
+	depends on BUSYBOX_CONFIG_SHELL_ASH || BUSYBOX_CONFIG_SHELL_HUSH
+	help
+	This option makes busybox shells to use $HISTFILESIZE variable
+	to set shell history size. Note that its max value is capped
+	by "History size" setting in library tuning section.
+
+config BUSYBOX_CONFIG_FEATURE_SH_EMBEDDED_SCRIPTS
+	bool "Embed scripts in the binary"
+	default BUSYBOX_DEFAULT_FEATURE_SH_EMBEDDED_SCRIPTS
+	depends on BUSYBOX_CONFIG_SHELL_ASH || BUSYBOX_CONFIG_SHELL_HUSH
+	help
+	Allow scripts to be compressed and embedded in the busybox
+	binary. The scripts should be placed in the 'embed' directory
+	at build time. Like applets, scripts can be run as
+	'busybox SCRIPT ...' or by linking their name to the binary.
+
+	This also allows applets to be implemented as scripts: place
+	the script in 'applets_sh' and a stub C file containing
+	configuration in the appropriate subsystem directory.
+
+endif # Options common to all shells
+
+endmenu
diff --git a/package/utils/busybox/config/sysklogd/Config.in b/package/utils/busybox/config/sysklogd/Config.in
new file mode 100644
index 0000000..1aa2ea0
--- /dev/null
+++ b/package/utils/busybox/config/sysklogd/Config.in
@@ -0,0 +1,171 @@
+# DO NOT EDIT. This file is generated from Config.src
+#
+# For a description of the syntax of this configuration file,
+# see docs/Kconfig-language.txt.
+#
+
+menu "System Logging Utilities"
+
+config BUSYBOX_CONFIG_KLOGD
+	bool "klogd (5.7 kb)"
+	default BUSYBOX_DEFAULT_KLOGD
+	help
+	klogd is a utility which intercepts and logs all
+	messages from the Linux kernel and sends the messages
+	out to the 'syslogd' utility so they can be logged. If
+	you wish to record the messages produced by the kernel,
+	you should enable this option.
+
+comment "klogd should not be used together with syslog to kernel printk buffer"
+	depends on BUSYBOX_CONFIG_KLOGD && BUSYBOX_CONFIG_FEATURE_KMSG_SYSLOG
+
+config BUSYBOX_CONFIG_FEATURE_KLOGD_KLOGCTL
+	bool "Use the klogctl() interface"
+	default BUSYBOX_DEFAULT_FEATURE_KLOGD_KLOGCTL
+	depends on BUSYBOX_CONFIG_KLOGD
+	help
+	The klogd applet supports two interfaces for reading
+	kernel messages. Linux provides the klogctl() interface
+	which allows reading messages from the kernel ring buffer
+	independently from the file system.
+
+	If you answer 'N' here, klogd will use the more portable
+	approach of reading them from /proc or a device node.
+	However, this method requires the file to be available.
+
+	If in doubt, say 'Y'.
+config BUSYBOX_CONFIG_LOGGER
+	bool "logger (6.3 kb)"
+	default BUSYBOX_DEFAULT_LOGGER
+	select BUSYBOX_CONFIG_FEATURE_SYSLOG
+	help
+	The logger utility allows you to send arbitrary text
+	messages to the system log (i.e. the 'syslogd' utility) so
+	they can be logged. This is generally used to help locate
+	problems that occur within programs and scripts.
+config BUSYBOX_CONFIG_LOGREAD
+	bool "logread (4.8 kb)"
+	default BUSYBOX_DEFAULT_LOGREAD
+	help
+	If you enabled Circular Buffer support, you almost
+	certainly want to enable this feature as well. This
+	utility will allow you to read the messages that are
+	stored in the syslogd circular buffer.
+
+config BUSYBOX_CONFIG_FEATURE_LOGREAD_REDUCED_LOCKING
+	bool "Double buffering"
+	default BUSYBOX_DEFAULT_FEATURE_LOGREAD_REDUCED_LOCKING
+	depends on BUSYBOX_CONFIG_LOGREAD
+	help
+	'logread' output to slow serial terminals can have
+	side effects on syslog because of the semaphore.
+	This option make logread to double buffer copy
+	from circular buffer, minimizing semaphore
+	contention at some minor memory expense.
+
+config BUSYBOX_CONFIG_SYSLOGD
+	bool "syslogd (13 kb)"
+	default BUSYBOX_DEFAULT_SYSLOGD
+	help
+	The syslogd utility is used to record logs of all the
+	significant events that occur on a system. Every
+	message that is logged records the date and time of the
+	event, and will generally also record the name of the
+	application that generated the message. When used in
+	conjunction with klogd, messages from the Linux kernel
+	can also be recorded. This is terribly useful,
+	especially for finding what happened when something goes
+	wrong. And something almost always will go wrong if
+	you wait long enough....
+
+config BUSYBOX_CONFIG_FEATURE_ROTATE_LOGFILE
+	bool "Rotate message files"
+	default BUSYBOX_DEFAULT_FEATURE_ROTATE_LOGFILE
+	depends on BUSYBOX_CONFIG_SYSLOGD
+	help
+	This enables syslogd to rotate the message files
+	on his own. No need to use an external rotate script.
+
+config BUSYBOX_CONFIG_FEATURE_REMOTE_LOG
+	bool "Remote Log support"
+	default BUSYBOX_DEFAULT_FEATURE_REMOTE_LOG
+	depends on BUSYBOX_CONFIG_SYSLOGD
+	help
+	When you enable this feature, the syslogd utility can
+	be used to send system log messages to another system
+	connected via a network. This allows the remote
+	machine to log all the system messages, which can be
+	terribly useful for reducing the number of serial
+	cables you use. It can also be a very good security
+	measure to prevent system logs from being tampered with
+	by an intruder.
+
+config BUSYBOX_CONFIG_FEATURE_SYSLOGD_DUP
+	bool "Support -D (drop dups) option"
+	default BUSYBOX_DEFAULT_FEATURE_SYSLOGD_DUP
+	depends on BUSYBOX_CONFIG_SYSLOGD
+	help
+	Option -D instructs syslogd to drop consecutive messages
+	which are totally the same.
+
+config BUSYBOX_CONFIG_FEATURE_SYSLOGD_CFG
+	bool "Support syslog.conf"
+	default BUSYBOX_DEFAULT_FEATURE_SYSLOGD_CFG
+	depends on BUSYBOX_CONFIG_SYSLOGD
+	help
+	Supports restricted syslogd config. See docs/syslog.conf.txt
+
+config BUSYBOX_CONFIG_FEATURE_SYSLOGD_PRECISE_TIMESTAMPS
+	bool "Include milliseconds in timestamps"
+	default BUSYBOX_DEFAULT_FEATURE_SYSLOGD_PRECISE_TIMESTAMPS
+	depends on BUSYBOX_CONFIG_SYSLOGD
+	help
+	Includes milliseconds (HH:MM:SS.mmm) in timestamp when
+	timestamps are added.
+
+config BUSYBOX_CONFIG_FEATURE_SYSLOGD_READ_BUFFER_SIZE
+	int "Read buffer size in bytes"
+	default BUSYBOX_DEFAULT_FEATURE_SYSLOGD_READ_BUFFER_SIZE
+	range 256 20000
+	depends on BUSYBOX_CONFIG_SYSLOGD
+	help
+	This option sets the size of the syslog read buffer.
+	Actual memory usage increases around five times the
+	change done here.
+
+config BUSYBOX_CONFIG_FEATURE_IPC_SYSLOG
+	bool "Circular Buffer support"
+	default BUSYBOX_DEFAULT_FEATURE_IPC_SYSLOG
+	depends on BUSYBOX_CONFIG_SYSLOGD
+	help
+	When you enable this feature, the syslogd utility will
+	use a circular buffer to record system log messages.
+	When the buffer is filled it will continue to overwrite
+	the oldest messages. This can be very useful for
+	systems with little or no permanent storage, since
+	otherwise system logs can eventually fill up your
+	entire filesystem, which may cause your system to
+	break badly.
+
+config BUSYBOX_CONFIG_FEATURE_IPC_SYSLOG_BUFFER_SIZE
+	int "Circular buffer size in Kbytes (minimum 4KB)"
+	default BUSYBOX_DEFAULT_FEATURE_IPC_SYSLOG_BUFFER_SIZE
+	range 4 2147483647
+	depends on BUSYBOX_CONFIG_FEATURE_IPC_SYSLOG
+	help
+	This option sets the size of the circular buffer
+	used to record system log messages.
+
+config BUSYBOX_CONFIG_FEATURE_KMSG_SYSLOG
+	bool "Linux kernel printk buffer support"
+	default BUSYBOX_DEFAULT_FEATURE_KMSG_SYSLOG
+	depends on BUSYBOX_CONFIG_SYSLOGD
+	help
+	When you enable this feature, the syslogd utility will
+	write system log message to the Linux kernel's printk buffer.
+	This can be used as a smaller alternative to the syslogd IPC
+	support, as klogd and logread aren't needed.
+
+	NOTICE: Syslog facilities in log entries needs kernel 3.5+.
+
+endmenu
diff --git a/package/utils/busybox/config/util-linux/Config.in b/package/utils/busybox/config/util-linux/Config.in
new file mode 100644
index 0000000..e3e59f1
--- /dev/null
+++ b/package/utils/busybox/config/util-linux/Config.in
@@ -0,0 +1,955 @@
+# DO NOT EDIT. This file is generated from Config.src
+#
+# For a description of the syntax of this configuration file,
+# see docs/Kconfig-language.txt.
+#
+
+menu "Linux System Utilities"
+
+config BUSYBOX_CONFIG_ACPID
+	bool "acpid (9 kb)"
+	default BUSYBOX_DEFAULT_ACPID
+	help
+	acpid listens to ACPI events coming either in textual form from
+	/proc/acpi/event (though it is marked deprecated it is still widely
+	used and _is_ a standard) or in binary form from specified evdevs
+	(just use /dev/input/event*).
+
+	It parses the event to retrieve ACTION and a possible PARAMETER.
+	It then spawns /etc/acpi/<ACTION>[/<PARAMETER>] either via run-parts
+	(if the resulting path is a directory) or directly as an executable.
+
+	N.B. acpid relies on run-parts so have the latter installed.
+
+config BUSYBOX_CONFIG_FEATURE_ACPID_COMPAT
+	bool "Accept and ignore redundant options"
+	default BUSYBOX_DEFAULT_FEATURE_ACPID_COMPAT
+	depends on BUSYBOX_CONFIG_ACPID
+	help
+	Accept and ignore compatibility options -g -m -s -S -v.
+config BUSYBOX_CONFIG_BLKDISCARD
+	bool "blkdiscard (4.3 kb)"
+	default BUSYBOX_DEFAULT_BLKDISCARD
+	help
+	blkdiscard discards sectors on a given device.
+config BUSYBOX_CONFIG_BLKID
+	bool "blkid (12 kb)"
+	default BUSYBOX_DEFAULT_BLKID
+	select BUSYBOX_CONFIG_VOLUMEID
+	help
+	Lists labels and UUIDs of all filesystems.
+
+config BUSYBOX_CONFIG_FEATURE_BLKID_TYPE
+	bool "Print filesystem type"
+	default BUSYBOX_DEFAULT_FEATURE_BLKID_TYPE
+	depends on BUSYBOX_CONFIG_BLKID
+	help
+	Show TYPE="filesystem type"
+config BUSYBOX_CONFIG_BLOCKDEV
+	bool "blockdev (2.3 kb)"
+	default BUSYBOX_DEFAULT_BLOCKDEV
+	help
+	Performs some ioctls with block devices.
+config BUSYBOX_CONFIG_CAL
+	bool "cal (5.8 kb)"
+	default BUSYBOX_DEFAULT_CAL
+	help
+	cal is used to display a monthly calendar.
+config BUSYBOX_CONFIG_CHRT
+	bool "chrt (4.7 kb)"
+	default BUSYBOX_DEFAULT_CHRT
+	help
+	Manipulate real-time attributes of a process.
+	This requires sched_{g,s}etparam support in your libc.
+config BUSYBOX_CONFIG_DMESG
+	bool "dmesg (3.7 kb)"
+	default BUSYBOX_DEFAULT_DMESG
+	help
+	dmesg is used to examine or control the kernel ring buffer. When the
+	Linux kernel prints messages to the system log, they are stored in
+	the kernel ring buffer. You can use dmesg to print the kernel's ring
+	buffer, clear the kernel ring buffer, change the size of the kernel
+	ring buffer, and change the priority level at which kernel messages
+	are also logged to the system console. Enable this option if you
+	wish to enable the 'dmesg' utility.
+
+config BUSYBOX_CONFIG_FEATURE_DMESG_PRETTY
+	bool "Pretty output"
+	default BUSYBOX_DEFAULT_FEATURE_DMESG_PRETTY
+	depends on BUSYBOX_CONFIG_DMESG
+	help
+	If you wish to scrub the syslog level from the output, say 'Y' here.
+	The syslog level is a string prefixed to every line with the form
+	"<#>".
+
+	With this option you will see:
+		# dmesg
+		Linux version 2.6.17.4 .....
+		BIOS-provided physical RAM map:
+		 BIOS-e820: 0000000000000000 - 000000000009f000 (usable)
+
+	Without this option you will see:
+		# dmesg
+		<5>Linux version 2.6.17.4 .....
+		<6>BIOS-provided physical RAM map:
+		<6> BIOS-e820: 0000000000000000 - 000000000009f000 (usable)
+config BUSYBOX_CONFIG_EJECT
+	bool "eject (4 kb)"
+	default BUSYBOX_DEFAULT_EJECT
+	help
+	Used to eject cdroms. (defaults to /dev/cdrom)
+
+config BUSYBOX_CONFIG_FEATURE_EJECT_SCSI
+	bool "SCSI support"
+	default BUSYBOX_DEFAULT_FEATURE_EJECT_SCSI
+	depends on BUSYBOX_CONFIG_EJECT
+	help
+	Add the -s option to eject, this allows to eject SCSI-Devices and
+	usb-storage devices.
+config BUSYBOX_CONFIG_FALLOCATE
+	bool "fallocate (4.1 kb)"
+	default BUSYBOX_DEFAULT_FALLOCATE
+	help
+	Preallocate space for files.
+config BUSYBOX_CONFIG_FATATTR
+	bool "fatattr (1.9 kb)"
+	default BUSYBOX_DEFAULT_FATATTR
+	help
+	fatattr lists or changes the file attributes on a fat file system.
+config BUSYBOX_CONFIG_FBSET
+	bool "fbset (5.9 kb)"
+	default BUSYBOX_DEFAULT_FBSET
+	help
+	fbset is used to show or change the settings of a Linux frame buffer
+	device. The frame buffer device provides a simple and unique
+	interface to access a graphics display. Enable this option
+	if you wish to enable the 'fbset' utility.
+
+config BUSYBOX_CONFIG_FEATURE_FBSET_FANCY
+	bool "Enable extra options"
+	default BUSYBOX_DEFAULT_FEATURE_FBSET_FANCY
+	depends on BUSYBOX_CONFIG_FBSET
+	help
+	This option enables extended fbset options, allowing one to set the
+	framebuffer size, color depth, etc. interface to access a graphics
+	display. Enable this option if you wish to enable extended fbset
+	options.
+
+config BUSYBOX_CONFIG_FEATURE_FBSET_READMODE
+	bool "Enable readmode support"
+	default BUSYBOX_DEFAULT_FEATURE_FBSET_READMODE
+	depends on BUSYBOX_CONFIG_FBSET
+	help
+	This option allows fbset to read the video mode database stored by
+	default BUSYBOX_DEFAULT_FEATURE_FBSET_READMODE /etc/fb.modes, which can be used to set frame buffer
+	device to pre-defined video modes.
+config BUSYBOX_CONFIG_FDFORMAT
+	bool "fdformat (4.4 kb)"
+	default BUSYBOX_DEFAULT_FDFORMAT
+	help
+	fdformat is used to low-level format a floppy disk.
+config BUSYBOX_CONFIG_FDISK
+	bool "fdisk (37 kb)"
+	default BUSYBOX_DEFAULT_FDISK
+	help
+	The fdisk utility is used to divide hard disks into one or more
+	logical disks, which are generally called partitions. This utility
+	can be used to list and edit the set of partitions or BSD style
+	'disk slices' that are defined on a hard drive.
+
+config BUSYBOX_CONFIG_FDISK_SUPPORT_LARGE_DISKS
+	bool "Support over 4GB disks"
+	default BUSYBOX_DEFAULT_FDISK_SUPPORT_LARGE_DISKS
+	depends on BUSYBOX_CONFIG_FDISK
+	depends on !BUSYBOX_CONFIG_LFS   # with LFS no special code is needed
+
+config BUSYBOX_CONFIG_FEATURE_FDISK_WRITABLE
+	bool "Write support"
+	default BUSYBOX_DEFAULT_FEATURE_FDISK_WRITABLE
+	depends on BUSYBOX_CONFIG_FDISK
+	help
+	Enabling this option allows you to create or change a partition table
+	and write those changes out to disk. If you leave this option
+	disabled, you will only be able to view the partition table.
+
+config BUSYBOX_CONFIG_FEATURE_AIX_LABEL
+	bool "Support AIX disklabels"
+	default BUSYBOX_DEFAULT_FEATURE_AIX_LABEL
+	depends on BUSYBOX_CONFIG_FDISK && BUSYBOX_CONFIG_FEATURE_FDISK_WRITABLE
+	help
+	Enabling this option allows you to create or change AIX disklabels.
+	Most people can safely leave this option disabled.
+
+config BUSYBOX_CONFIG_FEATURE_SGI_LABEL
+	bool "Support SGI disklabels"
+	default BUSYBOX_DEFAULT_FEATURE_SGI_LABEL
+	depends on BUSYBOX_CONFIG_FDISK && BUSYBOX_CONFIG_FEATURE_FDISK_WRITABLE
+	help
+	Enabling this option allows you to create or change SGI disklabels.
+	Most people can safely leave this option disabled.
+
+config BUSYBOX_CONFIG_FEATURE_SUN_LABEL
+	bool "Support SUN disklabels"
+	default BUSYBOX_DEFAULT_FEATURE_SUN_LABEL
+	depends on BUSYBOX_CONFIG_FDISK && BUSYBOX_CONFIG_FEATURE_FDISK_WRITABLE
+	help
+	Enabling this option allows you to create or change SUN disklabels.
+	Most people can safely leave this option disabled.
+
+config BUSYBOX_CONFIG_FEATURE_OSF_LABEL
+	bool "Support BSD disklabels"
+	default BUSYBOX_DEFAULT_FEATURE_OSF_LABEL
+	depends on BUSYBOX_CONFIG_FDISK && BUSYBOX_CONFIG_FEATURE_FDISK_WRITABLE
+	help
+	Enabling this option allows you to create or change BSD disklabels
+	and define and edit BSD disk slices.
+
+config BUSYBOX_CONFIG_FEATURE_GPT_LABEL
+	bool "Support GPT disklabels"
+	default BUSYBOX_DEFAULT_FEATURE_GPT_LABEL
+	depends on BUSYBOX_CONFIG_FDISK && BUSYBOX_CONFIG_FEATURE_FDISK_WRITABLE
+	help
+	Enabling this option allows you to view GUID Partition Table
+	disklabels.
+
+config BUSYBOX_CONFIG_FEATURE_FDISK_ADVANCED
+	bool "Support expert mode"
+	default BUSYBOX_DEFAULT_FEATURE_FDISK_ADVANCED
+	depends on BUSYBOX_CONFIG_FDISK && BUSYBOX_CONFIG_FEATURE_FDISK_WRITABLE
+	help
+	Enabling this option allows you to do terribly unsafe things like
+	define arbitrary drive geometry, move the beginning of data in a
+	partition, and similarly evil things. Unless you have a very good
+	reason you would be wise to leave this disabled.
+config BUSYBOX_CONFIG_FINDFS
+	bool "findfs (12 kb)"
+	default BUSYBOX_DEFAULT_FINDFS
+	select BUSYBOX_CONFIG_VOLUMEID
+	help
+	Prints the name of a filesystem with given label or UUID.
+config BUSYBOX_CONFIG_FLOCK
+	bool "flock (6.3 kb)"
+	default BUSYBOX_DEFAULT_FLOCK
+	help
+	Manage locks from shell scripts
+config BUSYBOX_CONFIG_FDFLUSH
+	bool "fdflush (1.3 kb)"
+	default BUSYBOX_DEFAULT_FDFLUSH
+	help
+	fdflush is only needed when changing media on slightly-broken
+	removable media drives. It is used to make Linux believe that a
+	hardware disk-change switch has been actuated, which causes Linux to
+	forget anything it has cached from the previous media. If you have
+	such a slightly-broken drive, you will need to run fdflush every time
+	you change a disk. Most people have working hardware and can safely
+	leave this disabled.
+
+config BUSYBOX_CONFIG_FREERAMDISK
+	bool "freeramdisk (1.3 kb)"
+	default BUSYBOX_DEFAULT_FREERAMDISK
+	help
+	Linux allows you to create ramdisks. This utility allows you to
+	delete them and completely free all memory that was used for the
+	ramdisk. For example, if you boot Linux into a ramdisk and later
+	pivot_root, you may want to free the memory that is allocated to the
+	ramdisk. If you have no use for freeing memory from a ramdisk, leave
+	this disabled.
+config BUSYBOX_CONFIG_FSCK_MINIX
+	bool "fsck.minix (13 kb)"
+	default BUSYBOX_DEFAULT_FSCK_MINIX
+	help
+	The minix filesystem is a nice, small, compact, read-write filesystem
+	with little overhead. It is not a journaling filesystem however and
+	can experience corruption if it is not properly unmounted or if the
+	power goes off in the middle of a write. This utility allows you to
+	check for and attempt to repair any corruption that occurs to a minix
+	filesystem.
+config BUSYBOX_CONFIG_FSFREEZE
+	bool "fsfreeze (3.5 kb)"
+	default BUSYBOX_DEFAULT_FSFREEZE
+	select BUSYBOX_CONFIG_LONG_OPTS
+	help
+	Halt new accesses and flush writes on a mounted filesystem.
+config BUSYBOX_CONFIG_FSTRIM
+	bool "fstrim (4.4 kb)"
+	default BUSYBOX_DEFAULT_FSTRIM
+	help
+	Discard unused blocks on a mounted filesystem.
+config BUSYBOX_CONFIG_GETOPT
+	bool "getopt (5.8 kb)"
+	default BUSYBOX_DEFAULT_GETOPT
+	help
+	The getopt utility is used to break up (parse) options in command
+	lines to make it easy to write complex shell scripts that also check
+	for legal (and illegal) options. If you want to write horribly
+	complex shell scripts, or use some horribly complex shell script
+	written by others, this utility may be for you. Most people will
+	wisely leave this disabled.
+
+config BUSYBOX_CONFIG_FEATURE_GETOPT_LONG
+	bool "Support -l LONGOPTs"
+	default BUSYBOX_DEFAULT_FEATURE_GETOPT_LONG
+	depends on BUSYBOX_CONFIG_GETOPT && BUSYBOX_CONFIG_LONG_OPTS
+	help
+	Enable support for long options (option -l).
+config BUSYBOX_CONFIG_HEXDUMP
+	bool "hexdump (8.6 kb)"
+	default BUSYBOX_DEFAULT_HEXDUMP
+	help
+	The hexdump utility is used to display binary data in a readable
+	way that is comparable to the output from most hex editors.
+
+config BUSYBOX_CONFIG_HD
+	bool "hd (7.8 kb)"
+	default BUSYBOX_DEFAULT_HD
+	help
+	hd is an alias to hexdump -C.
+config BUSYBOX_CONFIG_XXD
+	bool "xxd (8.9 kb)"
+	default BUSYBOX_DEFAULT_XXD
+	help
+	The xxd utility is used to display binary data in a readable
+	way that is comparable to the output from most hex editors.
+config BUSYBOX_CONFIG_HWCLOCK
+	bool "hwclock (5.8 kb)"
+	default BUSYBOX_DEFAULT_HWCLOCK
+	help
+	The hwclock utility is used to read and set the hardware clock
+	on a system. This is primarily used to set the current time on
+	shutdown in the hardware clock, so the hardware will keep the
+	correct time when Linux is _not_ running.
+
+config BUSYBOX_CONFIG_FEATURE_HWCLOCK_ADJTIME_FHS
+	bool "Use FHS /var/lib/hwclock/adjtime"
+	default BUSYBOX_DEFAULT_FEATURE_HWCLOCK_ADJTIME_FHS  # util-linux-ng in Fedora 13 still uses /etc/adjtime
+	depends on BUSYBOX_CONFIG_HWCLOCK
+	help
+	Starting with FHS 2.3, the adjtime state file is supposed to exist
+	at /var/lib/hwclock/adjtime instead of /etc/adjtime. If you wish
+	to use the FHS behavior, answer Y here, otherwise answer N for the
+	classic /etc/adjtime path.
+
+	pathname.com/fhs/pub/fhs-2.3.html#VARLIBHWCLOCKSTATEDIRECTORYFORHWCLO
+config BUSYBOX_CONFIG_IONICE
+	bool "ionice (3.8 kb)"
+	default BUSYBOX_DEFAULT_IONICE
+	help
+	Set/set program io scheduling class and priority
+	Requires kernel >= 2.6.13
+config BUSYBOX_CONFIG_IPCRM
+	bool "ipcrm (3.2 kb)"
+	default BUSYBOX_DEFAULT_IPCRM
+	help
+	The ipcrm utility allows the removal of System V interprocess
+	communication (IPC) objects and the associated data structures
+	from the system.
+config BUSYBOX_CONFIG_IPCS
+	bool "ipcs (11 kb)"
+	default BUSYBOX_DEFAULT_IPCS
+	help
+	The ipcs utility is used to provide information on the currently
+	allocated System V interprocess (IPC) objects in the system.
+config BUSYBOX_CONFIG_LAST
+	bool "last (6.1 kb)"
+	default BUSYBOX_DEFAULT_LAST
+	depends on BUSYBOX_CONFIG_FEATURE_WTMP
+	help
+	'last' displays a list of the last users that logged into the system.
+
+config BUSYBOX_CONFIG_FEATURE_LAST_FANCY
+	bool "Output extra information"
+	default BUSYBOX_DEFAULT_FEATURE_LAST_FANCY
+	depends on BUSYBOX_CONFIG_LAST
+	help
+	'last' displays detailed information about the last users that
+	logged into the system (mimics sysvinit last). +900 bytes.
+config BUSYBOX_CONFIG_LOSETUP
+	bool "losetup (5.5 kb)"
+	default BUSYBOX_DEFAULT_LOSETUP
+	help
+	losetup is used to associate or detach a loop device with a regular
+	file or block device, and to query the status of a loop device. This
+	version does not currently support enabling data encryption.
+config BUSYBOX_CONFIG_LSPCI
+	bool "lspci (6.3 kb)"
+	default BUSYBOX_DEFAULT_LSPCI
+	help
+	lspci is a utility for displaying information about PCI buses in the
+	system and devices connected to them.
+
+	This version uses sysfs (/sys/bus/pci/devices) only.
+config BUSYBOX_CONFIG_LSUSB
+	bool "lsusb (4.2 kb)"
+	default BUSYBOX_DEFAULT_LSUSB
+	help
+	lsusb is a utility for displaying information about USB buses in the
+	system and devices connected to them.
+
+	This version uses sysfs (/sys/bus/usb/devices) only.
+config BUSYBOX_CONFIG_MDEV
+	bool "mdev (17 kb)"
+	default BUSYBOX_DEFAULT_MDEV
+	help
+	mdev is a mini-udev implementation for dynamically creating device
+	nodes in the /dev directory.
+
+	For more information, please see docs/mdev.txt
+
+config BUSYBOX_CONFIG_FEATURE_MDEV_CONF
+	bool "Support /etc/mdev.conf"
+	default BUSYBOX_DEFAULT_FEATURE_MDEV_CONF
+	depends on BUSYBOX_CONFIG_MDEV
+	help
+	Add support for the mdev config file to control ownership and
+	permissions of the device nodes.
+
+	For more information, please see docs/mdev.txt
+
+config BUSYBOX_CONFIG_FEATURE_MDEV_RENAME
+	bool "Support subdirs/symlinks"
+	default BUSYBOX_DEFAULT_FEATURE_MDEV_RENAME
+	depends on BUSYBOX_CONFIG_FEATURE_MDEV_CONF
+	help
+	Add support for renaming devices and creating symlinks.
+
+	For more information, please see docs/mdev.txt
+
+config BUSYBOX_CONFIG_FEATURE_MDEV_RENAME_REGEXP
+	bool "Support regular expressions substitutions when renaming device"
+	default BUSYBOX_DEFAULT_FEATURE_MDEV_RENAME_REGEXP
+	depends on BUSYBOX_CONFIG_FEATURE_MDEV_RENAME
+	help
+	Add support for regular expressions substitutions when renaming
+	device.
+
+config BUSYBOX_CONFIG_FEATURE_MDEV_EXEC
+	bool "Support command execution at device addition/removal"
+	default BUSYBOX_DEFAULT_FEATURE_MDEV_EXEC
+	depends on BUSYBOX_CONFIG_FEATURE_MDEV_CONF
+	help
+	This adds support for an optional field to /etc/mdev.conf for
+	executing commands when devices are created/removed.
+
+	For more information, please see docs/mdev.txt
+
+config BUSYBOX_CONFIG_FEATURE_MDEV_LOAD_FIRMWARE
+	bool "Support loading of firmware"
+	default BUSYBOX_DEFAULT_FEATURE_MDEV_LOAD_FIRMWARE
+	depends on BUSYBOX_CONFIG_MDEV
+	help
+	Some devices need to load firmware before they can be usable.
+
+	These devices will request userspace look up the files in
+	/lib/firmware/ and if it exists, send it to the kernel for
+	loading into the hardware.
+
+config BUSYBOX_CONFIG_FEATURE_MDEV_DAEMON
+	bool "Support daemon mode"
+	default BUSYBOX_DEFAULT_FEATURE_MDEV_DAEMON
+	depends on BUSYBOX_CONFIG_MDEV
+	help
+	Adds the -d option to run mdev in daemon mode handling hotplug
+	events from the kernel like udev. If the system generates many
+	hotplug events this mode of operation will consume less
+	resources than registering mdev as hotplug helper or using the
+	uevent applet.
+config BUSYBOX_CONFIG_MESG
+	bool "mesg (1.4 kb)"
+	default BUSYBOX_DEFAULT_MESG
+	help
+	Mesg controls access to your terminal by others. It is typically
+	used to allow or disallow other users to write to your terminal
+
+config BUSYBOX_CONFIG_FEATURE_MESG_ENABLE_ONLY_GROUP
+	bool "Enable writing to tty only by group, not by everybody"
+	default BUSYBOX_DEFAULT_FEATURE_MESG_ENABLE_ONLY_GROUP
+	depends on BUSYBOX_CONFIG_MESG
+	help
+	Usually, ttys are owned by group "tty", and "write" tool is
+	setgid to this group. This way, "mesg y" only needs to enable
+	"write by owning group" bit in tty mode.
+
+	If you set this option to N, "mesg y" will enable writing
+	by anybody at all. This is not recommended.
+config BUSYBOX_CONFIG_MKE2FS
+	bool "mke2fs (10 kb)"
+	default BUSYBOX_DEFAULT_MKE2FS
+	help
+	Utility to create EXT2 filesystems.
+
+config BUSYBOX_CONFIG_MKFS_EXT2
+	bool "mkfs.ext2 (10 kb)"
+	default BUSYBOX_DEFAULT_MKFS_EXT2
+	help
+	Alias to "mke2fs".
+config BUSYBOX_CONFIG_MKFS_MINIX
+	bool "mkfs.minix (10 kb)"
+	default BUSYBOX_DEFAULT_MKFS_MINIX
+	help
+	The minix filesystem is a nice, small, compact, read-write filesystem
+	with little overhead. If you wish to be able to create minix
+	filesystems this utility will do the job for you.
+
+config BUSYBOX_CONFIG_FEATURE_MINIX2
+	bool "Support Minix fs v2 (fsck_minix/mkfs_minix)"
+	default BUSYBOX_DEFAULT_FEATURE_MINIX2
+	depends on BUSYBOX_CONFIG_FSCK_MINIX || BUSYBOX_CONFIG_MKFS_MINIX
+	help
+	If you wish to be able to create version 2 minix filesystems, enable
+	this. If you enabled 'mkfs_minix' then you almost certainly want to
+	be using the version 2 filesystem support.
+config BUSYBOX_CONFIG_MKFS_REISER
+	bool "mkfs_reiser"
+	default BUSYBOX_DEFAULT_MKFS_REISER
+	help
+	Utility to create ReiserFS filesystems.
+	Note: this applet needs a lot of testing and polishing.
+config BUSYBOX_CONFIG_MKDOSFS
+	bool "mkdosfs (7.2 kb)"
+	default BUSYBOX_DEFAULT_MKDOSFS
+	help
+	Utility to create FAT32 filesystems.
+
+config BUSYBOX_CONFIG_MKFS_VFAT
+	bool "mkfs.vfat (7.2 kb)"
+	default BUSYBOX_DEFAULT_MKFS_VFAT
+	help
+	Alias to "mkdosfs".
+config BUSYBOX_CONFIG_MKSWAP
+	bool "mkswap (6.3 kb)"
+	default BUSYBOX_DEFAULT_MKSWAP
+	help
+	The mkswap utility is used to configure a file or disk partition as
+	Linux swap space. This allows Linux to use the entire file or
+	partition as if it were additional RAM, which can greatly increase
+	the capability of low-memory machines. This additional memory is
+	much slower than real RAM, but can be very helpful at preventing your
+	applications being killed by the Linux out of memory (OOM) killer.
+	Once you have created swap space using 'mkswap' you need to enable
+	the swap space using the 'swapon' utility.
+
+config BUSYBOX_CONFIG_FEATURE_MKSWAP_UUID
+	bool "UUID support"
+	default BUSYBOX_DEFAULT_FEATURE_MKSWAP_UUID
+	depends on BUSYBOX_CONFIG_MKSWAP
+	help
+	Generate swap spaces with universally unique identifiers.
+config BUSYBOX_CONFIG_MORE
+	bool "more (7 kb)"
+	default BUSYBOX_DEFAULT_MORE
+	help
+	more is a simple utility which allows you to read text one screen
+	sized page at a time. If you want to read text that is larger than
+	the screen, and you are using anything faster than a 300 baud modem,
+	you will probably find this utility very helpful. If you don't have
+	any need to reading text files, you can leave this disabled.
+config BUSYBOX_CONFIG_MOUNT
+	bool "mount (23 kb)"
+	default BUSYBOX_DEFAULT_MOUNT
+	help
+	All files and filesystems in Unix are arranged into one big directory
+	tree. The 'mount' utility is used to graft a filesystem onto a
+	particular part of the tree. A filesystem can either live on a block
+	device, or it can be accessible over the network, as is the case with
+	NFS filesystems.
+
+config BUSYBOX_CONFIG_FEATURE_MOUNT_FAKE
+	bool "Support -f (fake mount)"
+	default BUSYBOX_DEFAULT_FEATURE_MOUNT_FAKE
+	depends on BUSYBOX_CONFIG_MOUNT
+	help
+	Enable support for faking a file system mount.
+
+config BUSYBOX_CONFIG_FEATURE_MOUNT_VERBOSE
+	bool "Support -v (verbose)"
+	default BUSYBOX_DEFAULT_FEATURE_MOUNT_VERBOSE
+	depends on BUSYBOX_CONFIG_MOUNT
+	help
+	Enable multi-level -v[vv...] verbose messages. Useful if you
+	debug mount problems and want to see what is exactly passed
+	to the kernel.
+
+config BUSYBOX_CONFIG_FEATURE_MOUNT_HELPERS
+	bool "Support mount helpers"
+	default BUSYBOX_DEFAULT_FEATURE_MOUNT_HELPERS
+	depends on BUSYBOX_CONFIG_MOUNT
+	help
+	Enable mounting of virtual file systems via external helpers.
+	E.g. "mount obexfs#-b00.11.22.33.44.55 /mnt" will in effect call
+	"obexfs -b00.11.22.33.44.55 /mnt"
+	Also "mount -t sometype [-o opts] fs /mnt" will try
+	"sometype [-o opts] fs /mnt" if simple mount syscall fails.
+	The idea is to use such virtual filesystems in /etc/fstab.
+
+config BUSYBOX_CONFIG_FEATURE_MOUNT_LABEL
+	bool "Support specifying devices by label or UUID"
+	default BUSYBOX_DEFAULT_FEATURE_MOUNT_LABEL
+	depends on BUSYBOX_CONFIG_MOUNT
+	select BUSYBOX_CONFIG_VOLUMEID
+	help
+	This allows for specifying a device by label or uuid, rather than by
+	name. This feature utilizes the same functionality as blkid/findfs.
+
+config BUSYBOX_CONFIG_FEATURE_MOUNT_NFS
+	bool "Support mounting NFS file systems on Linux < 2.6.23"
+	default BUSYBOX_DEFAULT_FEATURE_MOUNT_NFS
+	depends on BUSYBOX_CONFIG_MOUNT
+	select BUSYBOX_CONFIG_FEATURE_SYSLOG
+	help
+	Enable mounting of NFS file systems on Linux kernels prior
+	to version 2.6.23. Note that in this case mounting of NFS
+	over IPv6 will not be possible.
+
+	Note that this option links in RPC support from libc,
+	which is rather large (~10 kbytes on uclibc).
+
+config BUSYBOX_CONFIG_FEATURE_MOUNT_CIFS
+	bool "Support mounting CIFS/SMB file systems"
+	default BUSYBOX_DEFAULT_FEATURE_MOUNT_CIFS
+	depends on BUSYBOX_CONFIG_MOUNT
+	help
+	Enable support for samba mounts.
+
+config BUSYBOX_CONFIG_FEATURE_MOUNT_FLAGS
+	depends on BUSYBOX_CONFIG_MOUNT
+	bool "Support lots of -o flags"
+	default BUSYBOX_DEFAULT_FEATURE_MOUNT_FLAGS
+	help
+	Without this, mount only supports ro/rw/remount. With this, it
+	supports nosuid, suid, dev, nodev, exec, noexec, sync, async, atime,
+	noatime, diratime, nodiratime, loud, bind, move, shared, slave,
+	private, unbindable, rshared, rslave, rprivate, and runbindable.
+
+config BUSYBOX_CONFIG_FEATURE_MOUNT_FSTAB
+	depends on BUSYBOX_CONFIG_MOUNT
+	bool "Support /etc/fstab and -a (mount all)"
+	default BUSYBOX_DEFAULT_FEATURE_MOUNT_FSTAB
+	help
+	Support mount all and looking for files in /etc/fstab.
+
+config BUSYBOX_CONFIG_FEATURE_MOUNT_OTHERTAB
+	depends on BUSYBOX_CONFIG_FEATURE_MOUNT_FSTAB
+	bool "Support -T <alt_fstab>"
+	default BUSYBOX_DEFAULT_FEATURE_MOUNT_OTHERTAB
+	help
+	Support mount -T (specifying an alternate fstab)
+config BUSYBOX_CONFIG_MOUNTPOINT
+	bool "mountpoint (4.9 kb)"
+	default BUSYBOX_DEFAULT_MOUNTPOINT
+	help
+	mountpoint checks if the directory is a mountpoint.
+config BUSYBOX_CONFIG_NOLOGIN
+	bool "nologin"
+	default BUSYBOX_DEFAULT_NOLOGIN
+	depends on BUSYBOX_CONFIG_FEATURE_SH_EMBEDDED_SCRIPTS
+	help
+	Politely refuse a login
+
+config BUSYBOX_CONFIG_NOLOGIN_DEPENDENCIES
+	bool "Enable dependencies for nologin"
+	default BUSYBOX_DEFAULT_NOLOGIN_DEPENDENCIES  # Y default makes it harder to select single-applet test
+	depends on BUSYBOX_CONFIG_NOLOGIN
+	select BUSYBOX_CONFIG_CAT
+	select BUSYBOX_CONFIG_ECHO
+	select BUSYBOX_CONFIG_SLEEP
+	help
+	nologin is implemented as a shell script. It requires the
+	following in the runtime environment:
+		cat echo sleep
+	If you know these will be available externally you can
+	disable this option.
+config BUSYBOX_CONFIG_NSENTER
+	bool "nsenter (6.5 kb)"
+	default BUSYBOX_DEFAULT_NSENTER
+	help
+	Run program with namespaces of other processes.
+config BUSYBOX_CONFIG_PIVOT_ROOT
+	bool "pivot_root (1.1 kb)"
+	default BUSYBOX_DEFAULT_PIVOT_ROOT
+	help
+	The pivot_root utility swaps the mount points for the root filesystem
+	with some other mounted filesystem. This allows you to do all sorts
+	of wild and crazy things with your Linux system and is far more
+	powerful than 'chroot'.
+
+	Note: This is for initrd in linux 2.4. Under initramfs (introduced
+	in linux 2.6) use switch_root instead.
+config BUSYBOX_CONFIG_RDATE
+	bool "rdate (5.6 kb)"
+	default BUSYBOX_DEFAULT_RDATE
+	help
+	The rdate utility allows you to synchronize the date and time of your
+	system clock with the date and time of a remote networked system using
+	the RFC868 protocol, which is built into the inetd daemon on most
+	systems.
+config BUSYBOX_CONFIG_RDEV
+	bool "rdev (1.8 kb)"
+	default BUSYBOX_DEFAULT_RDEV
+	help
+	Print the device node associated with the filesystem mounted at '/'.
+config BUSYBOX_CONFIG_READPROFILE
+	bool "readprofile (7.1 kb)"
+	default BUSYBOX_DEFAULT_READPROFILE
+	help
+	This allows you to parse /proc/profile for basic profiling.
+config BUSYBOX_CONFIG_RENICE
+	bool "renice (4.2 kb)"
+	default BUSYBOX_DEFAULT_RENICE
+	help
+	Renice alters the scheduling priority of one or more running
+	processes.
+config BUSYBOX_CONFIG_REV
+	bool "rev (4.4 kb)"
+	default BUSYBOX_DEFAULT_REV
+	help
+	Reverse lines of a file or files.
+config BUSYBOX_CONFIG_RTCWAKE
+	bool "rtcwake (6.8 kb)"
+	default BUSYBOX_DEFAULT_RTCWAKE
+	help
+	Enter a system sleep state until specified wakeup time.
+config BUSYBOX_CONFIG_SCRIPT
+	bool "script (8.6 kb)"
+	default BUSYBOX_DEFAULT_SCRIPT
+	help
+	The script makes typescript of terminal session.
+config BUSYBOX_CONFIG_SCRIPTREPLAY
+	bool "scriptreplay (2.4 kb)"
+	default BUSYBOX_DEFAULT_SCRIPTREPLAY
+	help
+	This program replays a typescript, using timing information
+	given by script -t.
+config BUSYBOX_CONFIG_SETARCH
+	bool "setarch (3.6 kb)"
+	default BUSYBOX_DEFAULT_SETARCH
+	help
+	The linux32 utility is used to create a 32bit environment for the
+	specified program (usually a shell). It only makes sense to have
+	this util on a system that supports both 64bit and 32bit userland
+	(like amd64/x86, ppc64/ppc, sparc64/sparc, etc...).
+
+config BUSYBOX_CONFIG_LINUX32
+	bool "linux32 (3.3 kb)"
+	default BUSYBOX_DEFAULT_LINUX32
+	help
+	Alias to "setarch linux32".
+
+config BUSYBOX_CONFIG_LINUX64
+	bool "linux64 (3.3 kb)"
+	default BUSYBOX_DEFAULT_LINUX64
+	help
+	Alias to "setarch linux64".
+config BUSYBOX_CONFIG_SETPRIV
+	bool "setpriv (6.6 kb)"
+	default BUSYBOX_DEFAULT_SETPRIV
+	select BUSYBOX_CONFIG_LONG_OPTS
+	help
+	Run a program with different Linux privilege settings.
+	Requires kernel >= 3.5
+
+config BUSYBOX_CONFIG_FEATURE_SETPRIV_DUMP
+	bool "Support dumping current privilege state"
+	default BUSYBOX_DEFAULT_FEATURE_SETPRIV_DUMP
+	depends on BUSYBOX_CONFIG_SETPRIV
+	help
+	Enables the "--dump" switch to print out the current privilege
+	state. This is helpful for diagnosing problems.
+
+config BUSYBOX_CONFIG_FEATURE_SETPRIV_CAPABILITIES
+	bool "Support capabilities"
+	default BUSYBOX_DEFAULT_FEATURE_SETPRIV_CAPABILITIES
+	depends on BUSYBOX_CONFIG_SETPRIV
+	help
+	Capabilities can be used to grant processes additional rights
+	without the necessity to always execute as the root user.
+	Enabling this option enables "--dump" to show information on
+	capabilities.
+
+config BUSYBOX_CONFIG_FEATURE_SETPRIV_CAPABILITY_NAMES
+	bool "Support capability names"
+	default BUSYBOX_DEFAULT_FEATURE_SETPRIV_CAPABILITY_NAMES
+	depends on BUSYBOX_CONFIG_SETPRIV && BUSYBOX_CONFIG_FEATURE_SETPRIV_CAPABILITIES
+	help
+	Capabilities can be either referenced via a human-readble name,
+	e.g. "net_admin", or using their index, e.g. "cap_12". Enabling
+	this option allows using the human-readable names in addition to
+	the index-based names.
+config BUSYBOX_CONFIG_SETSID
+	bool "setsid (3.6 kb)"
+	default BUSYBOX_DEFAULT_SETSID
+	help
+	setsid runs a program in a new session
+config BUSYBOX_CONFIG_SWAPON
+	bool "swapon (15 kb)"
+	default BUSYBOX_DEFAULT_SWAPON
+	help
+	Once you have created some swap space using 'mkswap', you also need
+	to enable your swap space with the 'swapon' utility. The 'swapoff'
+	utility is used, typically at system shutdown, to disable any swap
+	space. If you are not using any swap space, you can leave this
+	option disabled.
+
+config BUSYBOX_CONFIG_FEATURE_SWAPON_DISCARD
+	bool "Support discard option -d"
+	default BUSYBOX_DEFAULT_FEATURE_SWAPON_DISCARD
+	depends on BUSYBOX_CONFIG_SWAPON
+	help
+	Enable support for discarding swap area blocks at swapon and/or as
+	the kernel frees them. This option enables both the -d option on
+	'swapon' and the 'discard' option for swap entries in /etc/fstab.
+
+config BUSYBOX_CONFIG_FEATURE_SWAPON_PRI
+	bool "Support priority option -p"
+	default BUSYBOX_DEFAULT_FEATURE_SWAPON_PRI
+	depends on BUSYBOX_CONFIG_SWAPON
+	help
+	Enable support for setting swap device priority in swapon.
+
+config BUSYBOX_CONFIG_SWAPOFF
+	bool "swapoff (14 kb)"
+	default BUSYBOX_DEFAULT_SWAPOFF
+
+config BUSYBOX_CONFIG_FEATURE_SWAPONOFF_LABEL
+	bool "Support specifying devices by label or UUID"
+	default BUSYBOX_DEFAULT_FEATURE_SWAPONOFF_LABEL
+	depends on BUSYBOX_CONFIG_SWAPON || BUSYBOX_CONFIG_SWAPOFF
+	select BUSYBOX_CONFIG_VOLUMEID
+	help
+	This allows for specifying a device by label or uuid, rather than by
+	name. This feature utilizes the same functionality as blkid/findfs.
+config BUSYBOX_CONFIG_SWITCH_ROOT
+	bool "switch_root (5.5 kb)"
+	default BUSYBOX_DEFAULT_SWITCH_ROOT
+	help
+	The switch_root utility is used from initramfs to select a new
+	root device. Under initramfs, you have to use this instead of
+	pivot_root. (Stop reading here if you don't care why.)
+
+	Booting with initramfs extracts a gzipped cpio archive into rootfs
+	(which is a variant of ramfs/tmpfs). Because rootfs can't be moved
+	or unmounted*, pivot_root will not work from initramfs. Instead,
+	switch_root deletes everything out of rootfs (including itself),
+	does a mount --move that overmounts rootfs with the new root, and
+	then execs the specified init program.
+
+	* Because the Linux kernel uses rootfs internally as the starting
+	and ending point for searching through the kernel's doubly linked
+	list of active mount points. That's why.
+
+config BUSYBOX_CONFIG_TASKSET
+	bool "taskset (4.2 kb)"
+	default BUSYBOX_DEFAULT_TASKSET
+	help
+	Retrieve or set a processes's CPU affinity.
+	This requires sched_{g,s}etaffinity support in your libc.
+
+config BUSYBOX_CONFIG_FEATURE_TASKSET_FANCY
+	bool "Fancy output"
+	default BUSYBOX_DEFAULT_FEATURE_TASKSET_FANCY
+	depends on BUSYBOX_CONFIG_TASKSET
+	help
+	Needed for machines with more than 32-64 CPUs:
+	affinity parameter 0xHHHHHHHHHHHHHHHHHHHH can be arbitrarily long
+	in this case. Otherwise, it is limited to sizeof(long).
+
+config BUSYBOX_CONFIG_FEATURE_TASKSET_CPULIST
+	bool "CPU list support (-c option)"
+	default BUSYBOX_DEFAULT_FEATURE_TASKSET_CPULIST
+	depends on BUSYBOX_CONFIG_FEATURE_TASKSET_FANCY
+	help
+	Add support for taking/printing affinity as CPU list when '-c'
+	option is used. For example, it prints '0-3,7' instead of mask '8f'.
+config BUSYBOX_CONFIG_UEVENT
+	bool "uevent (3.1 kb)"
+	default BUSYBOX_DEFAULT_UEVENT
+	help
+	uevent is a netlink listener for kernel uevent notifications
+	sent via netlink. It is usually used for dynamic device creation.
+config BUSYBOX_CONFIG_UMOUNT
+	bool "umount (5.1 kb)"
+	default BUSYBOX_DEFAULT_UMOUNT
+	help
+	When you want to remove a mounted filesystem from its current mount
+	point, for example when you are shutting down the system, the
+	'umount' utility is the tool to use. If you enabled the 'mount'
+	utility, you almost certainly also want to enable 'umount'.
+
+config BUSYBOX_CONFIG_FEATURE_UMOUNT_ALL
+	bool "Support -a (unmount all)"
+	default BUSYBOX_DEFAULT_FEATURE_UMOUNT_ALL
+	depends on BUSYBOX_CONFIG_UMOUNT
+	help
+	Support -a option to unmount all currently mounted filesystems.
+config BUSYBOX_CONFIG_UNSHARE
+	bool "unshare (7.2 kb)"
+	default BUSYBOX_DEFAULT_UNSHARE
+	depends on !BUSYBOX_CONFIG_NOMMU
+	select BUSYBOX_CONFIG_LONG_OPTS
+	help
+	Run program with some namespaces unshared from parent.
+config BUSYBOX_CONFIG_WALL
+	bool "wall (2.6 kb)"
+	default BUSYBOX_DEFAULT_WALL
+	depends on BUSYBOX_CONFIG_FEATURE_UTMP
+	help
+	Write a message to all users that are logged in.
+
+comment "Common options for mount/umount"
+	depends on BUSYBOX_CONFIG_MOUNT || BUSYBOX_CONFIG_UMOUNT
+
+config BUSYBOX_CONFIG_FEATURE_MOUNT_LOOP
+	bool "Support loopback mounts"
+	default BUSYBOX_DEFAULT_FEATURE_MOUNT_LOOP
+	depends on BUSYBOX_CONFIG_MOUNT || BUSYBOX_CONFIG_UMOUNT
+	help
+	Enabling this feature allows automatic mounting of files (containing
+	filesystem images) via the linux kernel's loopback devices.
+	The mount command will detect you are trying to mount a file instead
+	of a block device, and transparently associate the file with a
+	loopback device. The umount command will also free that loopback
+	device.
+
+	You can still use the 'losetup' utility (to manually associate files
+	with loop devices) if you need to do something advanced, such as
+	specify an offset or cryptographic options to the loopback device.
+	(If you don't want umount to free the loop device, use "umount -D".)
+
+config BUSYBOX_CONFIG_FEATURE_MOUNT_LOOP_CREATE
+	bool "Create new loopback devices if needed"
+	default BUSYBOX_DEFAULT_FEATURE_MOUNT_LOOP_CREATE
+	depends on BUSYBOX_CONFIG_FEATURE_MOUNT_LOOP
+	help
+	Linux kernels >= 2.6.24 support unlimited loopback devices. They are
+	allocated for use when trying to use a loop device. The loop device
+	must however exist.
+
+	This feature lets mount to try to create next /dev/loopN device
+	if it does not find a free one.
+
+config BUSYBOX_CONFIG_FEATURE_MTAB_SUPPORT
+	bool "Support old /etc/mtab file"
+	default BUSYBOX_DEFAULT_FEATURE_MTAB_SUPPORT
+	depends on BUSYBOX_CONFIG_MOUNT || BUSYBOX_CONFIG_UMOUNT
+	select BUSYBOX_CONFIG_FEATURE_MOUNT_FAKE
+	help
+	Historically, Unix systems kept track of the currently mounted
+	partitions in the file "/etc/mtab". These days, the kernel exports
+	the list of currently mounted partitions in "/proc/mounts", rendering
+	the old mtab file obsolete. (In modern systems, /etc/mtab should be
+	a symlink to /proc/mounts.)
+
+	The only reason to have mount maintain an /etc/mtab file itself is if
+	your stripped-down embedded system does not have a /proc directory.
+	If you must use this, keep in mind it's inherently brittle (for
+	example a mount under chroot won't update it), can't handle modern
+	features like separate per-process filesystem namespaces, requires
+	that your /etc directory be writable, tends to get easily confused
+	by --bind or --move mounts, won't update if you rename a directory
+	that contains a mount point, and so on. (In brief: avoid.)
+
+	About the only reason to use this is if you've removed /proc from
+	your kernel.
+
+source "volume_id/Config.in"
+
+endmenu
diff --git a/package/utils/busybox/config/util-linux/volume_id/Config.in b/package/utils/busybox/config/util-linux/volume_id/Config.in
new file mode 100644
index 0000000..57d8258
--- /dev/null
+++ b/package/utils/busybox/config/util-linux/volume_id/Config.in
@@ -0,0 +1,203 @@
+# DO NOT EDIT. This file is generated from Config.src
+#
+# For a description of the syntax of this configuration file,
+# see docs/Kconfig-language.txt.
+#
+
+config BUSYBOX_CONFIG_VOLUMEID
+	bool #No description makes it a hidden option
+	default BUSYBOX_DEFAULT_VOLUMEID
+
+menu "Filesystem/Volume identification"
+	depends on BUSYBOX_CONFIG_VOLUMEID
+
+config BUSYBOX_CONFIG_FEATURE_VOLUMEID_BCACHE
+	bool "bcache filesystem"
+	default BUSYBOX_DEFAULT_FEATURE_VOLUMEID_BCACHE
+	depends on BUSYBOX_CONFIG_VOLUMEID
+config BUSYBOX_CONFIG_FEATURE_VOLUMEID_BTRFS
+	bool "btrfs filesystem"
+	default BUSYBOX_DEFAULT_FEATURE_VOLUMEID_BTRFS
+	depends on BUSYBOX_CONFIG_VOLUMEID
+config BUSYBOX_CONFIG_FEATURE_VOLUMEID_CRAMFS
+	bool "cramfs filesystem"
+	default BUSYBOX_DEFAULT_FEATURE_VOLUMEID_CRAMFS
+	depends on BUSYBOX_CONFIG_VOLUMEID
+config BUSYBOX_CONFIG_FEATURE_VOLUMEID_EROFS
+	bool "erofs filesystem"
+	default BUSYBOX_DEFAULT_FEATURE_VOLUMEID_EROFS
+	depends on BUSYBOX_CONFIG_VOLUMEID
+	help
+	Erofs is a compressed readonly filesystem for Linux.
+config BUSYBOX_CONFIG_FEATURE_VOLUMEID_EXFAT
+	bool "exFAT filesystem"
+	default BUSYBOX_DEFAULT_FEATURE_VOLUMEID_EXFAT
+	depends on BUSYBOX_CONFIG_VOLUMEID
+	help
+	exFAT (extended FAT) is a proprietary file system designed especially
+	for flash drives. It has many features from NTFS, but with less
+	overhead. exFAT is used on most SDXC cards for consumer electronics.
+config BUSYBOX_CONFIG_FEATURE_VOLUMEID_EXT
+	bool "Ext filesystem"
+	default BUSYBOX_DEFAULT_FEATURE_VOLUMEID_EXT
+	depends on BUSYBOX_CONFIG_VOLUMEID
+config BUSYBOX_CONFIG_FEATURE_VOLUMEID_F2FS
+	bool "f2fs filesystem"
+	default BUSYBOX_DEFAULT_FEATURE_VOLUMEID_F2FS
+	depends on BUSYBOX_CONFIG_VOLUMEID
+	help
+	F2FS (aka Flash-Friendly File System) is a log-structured file system,
+	which is adapted to newer forms of storage. F2FS also remedies some
+	known issues of the older log structured file systems, such as high
+	cleaning overhead.
+config BUSYBOX_CONFIG_FEATURE_VOLUMEID_FAT
+	bool "fat filesystem"
+	default BUSYBOX_DEFAULT_FEATURE_VOLUMEID_FAT
+	depends on BUSYBOX_CONFIG_VOLUMEID
+config BUSYBOX_CONFIG_FEATURE_VOLUMEID_HFS
+	bool "hfs filesystem"
+	default BUSYBOX_DEFAULT_FEATURE_VOLUMEID_HFS
+	depends on BUSYBOX_CONFIG_VOLUMEID
+config BUSYBOX_CONFIG_FEATURE_VOLUMEID_ISO9660
+	bool "iso9660 filesystem"
+	default BUSYBOX_DEFAULT_FEATURE_VOLUMEID_ISO9660
+	depends on BUSYBOX_CONFIG_VOLUMEID
+config BUSYBOX_CONFIG_FEATURE_VOLUMEID_JFS
+	bool "jfs filesystem"
+	default BUSYBOX_DEFAULT_FEATURE_VOLUMEID_JFS
+	depends on BUSYBOX_CONFIG_VOLUMEID
+config BUSYBOX_CONFIG_FEATURE_VOLUMEID_LFS
+	bool "LittleFS filesystem"
+	default BUSYBOX_DEFAULT_FEATURE_VOLUMEID_LFS
+	depends on BUSYBOX_CONFIG_VOLUMEID && BUSYBOX_CONFIG_FEATURE_BLKID_TYPE
+	help
+	LittleFS is a small fail-safe filesystem designed for embedded
+	systems. It has strong copy-on-write guarantees and storage on disk
+	is always kept in a valid state. It also provides a form of dynamic
+	wear levelling for systems that can not fit a full flash translation
+	layer.
+config BUSYBOX_CONFIG_FEATURE_VOLUMEID_LINUXRAID
+	bool "linuxraid"
+	default BUSYBOX_DEFAULT_FEATURE_VOLUMEID_LINUXRAID
+	depends on BUSYBOX_CONFIG_VOLUMEID
+config BUSYBOX_CONFIG_FEATURE_VOLUMEID_LINUXSWAP
+	bool "linux swap filesystem"
+	default BUSYBOX_DEFAULT_FEATURE_VOLUMEID_LINUXSWAP
+	depends on BUSYBOX_CONFIG_VOLUMEID
+config BUSYBOX_CONFIG_FEATURE_VOLUMEID_LUKS
+	bool "luks filesystem"
+	default BUSYBOX_DEFAULT_FEATURE_VOLUMEID_LUKS
+	depends on BUSYBOX_CONFIG_VOLUMEID
+config BUSYBOX_CONFIG_FEATURE_VOLUMEID_MINIX
+	bool "minix filesystem"
+	default BUSYBOX_DEFAULT_FEATURE_VOLUMEID_MINIX
+	depends on BUSYBOX_CONFIG_VOLUMEID
+config BUSYBOX_CONFIG_FEATURE_VOLUMEID_NILFS
+	bool "nilfs filesystem"
+	default BUSYBOX_DEFAULT_FEATURE_VOLUMEID_NILFS
+	depends on BUSYBOX_CONFIG_VOLUMEID
+	help
+	NILFS is a New Implementation of a Log-Structured File System (LFS)
+	that supports continuous snapshots. This provides features like
+	versioning of the entire filesystem, restoration of files that
+	were deleted a few minutes ago. NILFS keeps consistency like
+	conventional LFS, so it provides quick recovery after system crashes.
+
+	The possible use of NILFS includes versioning, tamper detection,
+	SOX compliance logging, and so forth. It can serve as an alternative
+	filesystem for Linux desktop environment, or as a basis of advanced
+	storage appliances.
+config BUSYBOX_CONFIG_FEATURE_VOLUMEID_NTFS
+	bool "ntfs filesystem"
+	default BUSYBOX_DEFAULT_FEATURE_VOLUMEID_NTFS
+	depends on BUSYBOX_CONFIG_VOLUMEID
+config BUSYBOX_CONFIG_FEATURE_VOLUMEID_OCFS2
+	bool "ocfs2 filesystem"
+	default BUSYBOX_DEFAULT_FEATURE_VOLUMEID_OCFS2
+	depends on BUSYBOX_CONFIG_VOLUMEID
+config BUSYBOX_CONFIG_FEATURE_VOLUMEID_REISERFS
+	bool "Reiser filesystem"
+	default BUSYBOX_DEFAULT_FEATURE_VOLUMEID_REISERFS
+	depends on BUSYBOX_CONFIG_VOLUMEID
+config BUSYBOX_CONFIG_FEATURE_VOLUMEID_ROMFS
+	bool "romfs filesystem"
+	default BUSYBOX_DEFAULT_FEATURE_VOLUMEID_ROMFS
+	depends on BUSYBOX_CONFIG_VOLUMEID
+config BUSYBOX_CONFIG_FEATURE_VOLUMEID_SQUASHFS
+	bool "SquashFS filesystem"
+	default BUSYBOX_DEFAULT_FEATURE_VOLUMEID_SQUASHFS
+	depends on BUSYBOX_CONFIG_VOLUMEID && BUSYBOX_CONFIG_FEATURE_BLKID_TYPE
+	help
+	Squashfs is a compressed read-only filesystem for Linux. Squashfs is
+	intended for general read-only filesystem use and in constrained block
+	device/memory systems (e.g. embedded systems) where low overhead is
+	needed.
+config BUSYBOX_CONFIG_FEATURE_VOLUMEID_SYSV
+	bool "sysv filesystem"
+	default BUSYBOX_DEFAULT_FEATURE_VOLUMEID_SYSV
+	depends on BUSYBOX_CONFIG_VOLUMEID
+config BUSYBOX_CONFIG_FEATURE_VOLUMEID_UBIFS
+	bool "UBIFS filesystem"
+	default BUSYBOX_DEFAULT_FEATURE_VOLUMEID_UBIFS
+	depends on BUSYBOX_CONFIG_VOLUMEID
+	help
+	UBIFS (Unsorted Block Image File System) is a file
+	system for use with raw flash memory media.
+config BUSYBOX_CONFIG_FEATURE_VOLUMEID_UDF
+	bool "udf filesystem"
+	default BUSYBOX_DEFAULT_FEATURE_VOLUMEID_UDF
+	depends on BUSYBOX_CONFIG_VOLUMEID
+### config FEATURE_VOLUMEID_HIGHPOINTRAID
+###	bool "highpoint raid"
+###	default y
+###	depends on VOLUMEID
+### config FEATURE_VOLUMEID_HPFS
+###	bool "hpfs filesystem"
+###	default y
+###	depends on VOLUMEID
+### config FEATURE_VOLUMEID_ISWRAID
+###	bool "intel raid"
+###	default y
+###	depends on VOLUMEID
+### config FEATURE_VOLUMEID_LSIRAID
+###	bool "lsi raid"
+###	default y
+###	depends on VOLUMEID
+### config FEATURE_VOLUMEID_LVM
+###	bool "lvm"
+###	default y
+###	depends on VOLUMEID
+### config FEATURE_VOLUMEID_MAC
+###	bool "mac filesystem"
+###	default y
+###	depends on VOLUMEID
+### config FEATURE_VOLUMEID_MSDOS
+###	bool "msdos filesystem"
+###	default y
+###	depends on VOLUMEID
+### config FEATURE_VOLUMEID_NVIDIARAID
+###	bool "nvidia raid"
+###	default y
+###	depends on VOLUMEID
+### config FEATURE_VOLUMEID_PROMISERAID
+###	bool "promise raid"
+###	default y
+###	depends on VOLUMEID
+### config FEATURE_VOLUMEID_SILICONRAID
+###	bool "silicon raid"
+###	default y
+###	depends on VOLUMEID
+### config FEATURE_VOLUMEID_UFS
+###	bool "ufs filesystem"
+###	default y
+###	depends on VOLUMEID
+### config FEATURE_VOLUMEID_VIARAID
+###	bool "via raid"
+###	default y
+###	depends on VOLUMEID
+config BUSYBOX_CONFIG_FEATURE_VOLUMEID_XFS
+	bool "xfs filesystem"
+	default BUSYBOX_DEFAULT_FEATURE_VOLUMEID_XFS
+	depends on BUSYBOX_CONFIG_VOLUMEID
+
+endmenu
diff --git a/package/utils/busybox/convert_defaults.pl b/package/utils/busybox/convert_defaults.pl
new file mode 100755
index 0000000..dada6ef
--- /dev/null
+++ b/package/utils/busybox/convert_defaults.pl
@@ -0,0 +1,13 @@
+#!/usr/bin/env perl
+
+while (<>) {
+	/^(# )?CONFIG_([^=]+)(=(.+)| is not set)/ and do {
+		my $default = $4;
+		$1 and $default = "n";
+		my $name = $2;
+		my $type = "bool";
+		$default =~ /^\"/ and $type = "string";
+		$default =~ /^\d/ and $type = "int";
+		print "config BUSYBOX_DEFAULT_$name\n\t$type\n\tdefault $default\n";
+	};
+}
diff --git a/package/utils/busybox/convert_menuconfig.pl b/package/utils/busybox/convert_menuconfig.pl
new file mode 100755
index 0000000..7051880
--- /dev/null
+++ b/package/utils/busybox/convert_menuconfig.pl
@@ -0,0 +1,76 @@
+#!/usr/bin/perl
+# 
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+use strict;
+my $PATH = $ARGV[0];
+($PATH and -d $PATH) or die 'invalid path';
+
+my %config;
+
+open FIND, "find \"$PATH\" -name Config.in |";
+while (<FIND>) {
+	chomp;
+	my $input = $_;
+	my $output = $input;
+	my $replace = quotemeta($PATH);
+	$output =~ s/^$replace\///g;
+	$output =~ s/sysdeps\/linux\///g;
+	print STDERR "$input => $output\n";
+	$output =~ /^(.+)\/[^\/]+$/ and system("mkdir -p $1");
+
+	open INPUT, $input;
+	open OUTPUT, ">$output";
+	my ($cur, $default_set, $line);
+	while ($line = <INPUT>) {
+		next if $line =~ /^\s*mainmenu/;
+
+		# FIXME: make this dynamic
+		$line =~ s/default FEATURE_BUFFERS_USE_MALLOC/default FEATURE_BUFFERS_GO_ON_STACK/;
+		$line =~ s/default FEATURE_SH_IS_NONE/default FEATURE_SH_IS_ASH/;
+
+		if ($line =~ /^\s*config\s*([\w_]+)/) {
+			$cur = $1;
+			undef $default_set;
+		}
+		if ($line =~ /^\s*(menu|choice|end|source)/) {
+			undef $cur;
+			undef $default_set;
+		}
+		$line =~ s/^(\s*source\s+)([^\/]+\/)*([^\/]+\/[^\/]+)$/$1$3/;
+		if ($line =~ /^(\s*range\s*)(\w+)(\s+)(\w+)\s*$/) {
+			my $prefix = $1;
+			my $r1 = $2;
+			my $r2 = $4;
+			$r1 =~ s/^([a-zA-Z]+)/BUSYBOX_CONFIG_$1/;
+			$r2 =~ s/^([a-zA-Z]+)/BUSYBOX_CONFIG_$1/;
+			$line = "$prefix$r1 $r2\n";
+		}
+
+		$line =~ s/^(\s*(prompt "[^"]+" if|config|depends|depends on|select|default|default \w if)\s+\!?)([A-Z_])/$1BUSYBOX_CONFIG_$3/g;
+		$line =~ s/(( \|\| | \&\& | \( )!?)([A-Z_])/$1BUSYBOX_CONFIG_$3/g;
+		$line =~ s/(\( ?!?)([A-Z_]+ (\|\||&&))/$1BUSYBOX_CONFIG_$2/g;
+
+		if ($cur) {
+			($cur eq 'LFS') and do {
+				$line =~ s/^(\s*(bool|tristate|string))\s*".+"$/$1/;
+			};
+			if ($line =~ /^\s*default/) {
+				my $c;
+				$default_set = 1;
+				$c = "BUSYBOX_DEFAULT_$cur";
+
+				$line =~ s/^(\s*default\s*)(\w+|"[^"]*")(.*)/$1$c$3/;
+			}
+		}
+
+		print OUTPUT $line;
+	}
+	close OUTPUT;
+	close INPUT;
+}
+close FIND;
diff --git a/package/utils/busybox/files/cron b/package/utils/busybox/files/cron
new file mode 100755
index 0000000..4efdfa5
--- /dev/null
+++ b/package/utils/busybox/files/cron
@@ -0,0 +1,41 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2006-2011 OpenWrt.org
+
+START=50
+
+USE_PROCD=1
+PROG=/usr/sbin/crond
+
+validate_cron_section() {
+	uci_validate_section system system "${1}" \
+		'cronloglevel:uinteger'
+}
+
+start_service() {
+	[ -z "$(ls /etc/crontabs/)" ] && return 1
+
+	loglevel="$(uci_get "system.@system[0].cronloglevel")"
+
+	[ -z "${loglevel}" ] || {
+		/sbin/validate_data uinteger "${loglevel}" 2>/dev/null
+		[ "$?" -eq 0 ] || {
+			echo "validation failed"
+			return 1
+		}
+	}
+
+	mkdir -p /var/spool/cron
+	ln -s /etc/crontabs /var/spool/cron/ 2>/dev/null
+
+	procd_open_instance
+	procd_set_param command "$PROG" -f -c /etc/crontabs -l "${loglevel:-5}"
+	for crontab in /etc/crontabs/*; do
+		 procd_set_param file "$crontab"
+	done
+	procd_set_param respawn
+	procd_close_instance
+}
+
+service_triggers() {
+	procd_add_validation validate_cron_section
+}
diff --git a/package/utils/busybox/files/ntpd-hotplug b/package/utils/busybox/files/ntpd-hotplug
new file mode 100755
index 0000000..f09f5bb
--- /dev/null
+++ b/package/utils/busybox/files/ntpd-hotplug
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+. /usr/share/libubox/jshn.sh
+
+addenv="$( env | while read line; do echo "json_add_string \"\" \"$line\";"; done )"
+json_init
+json_add_array env
+json_add_string "" "ACTION=$1"
+eval "$addenv"
+json_close_array env
+
+ubus call hotplug.ntp call "$(json_dump)"
diff --git a/package/utils/busybox/files/ntpd.capabilities b/package/utils/busybox/files/ntpd.capabilities
new file mode 100644
index 0000000..8a05dba
--- /dev/null
+++ b/package/utils/busybox/files/ntpd.capabilities
@@ -0,0 +1,22 @@
+{
+	"bounding": [
+		"CAP_NET_BIND_SERVICE",
+		"CAP_SYS_TIME"
+	],
+	"effective": [
+		"CAP_NET_BIND_SERVICE",
+		"CAP_SYS_TIME"
+	],
+	"ambient": [
+		"CAP_NET_BIND_SERVICE",
+		"CAP_SYS_TIME"
+	],
+	"permitted": [
+		"CAP_NET_BIND_SERVICE",
+		"CAP_SYS_TIME"
+	],
+	"inheritable": [
+		"CAP_NET_BIND_SERVICE",
+		"CAP_SYS_TIME"
+	]
+}
diff --git a/package/utils/busybox/files/ntpd_acl.json b/package/utils/busybox/files/ntpd_acl.json
new file mode 100644
index 0000000..991793d
--- /dev/null
+++ b/package/utils/busybox/files/ntpd_acl.json
@@ -0,0 +1,8 @@
+{
+	"user": "ntp",
+	"access": {
+		"hotplug.ntp": {
+			"methods": [ "call" ]
+		}
+	}
+}
diff --git a/package/utils/busybox/files/sysntpd b/package/utils/busybox/files/sysntpd
new file mode 100755
index 0000000..80baaa5
--- /dev/null
+++ b/package/utils/busybox/files/sysntpd
@@ -0,0 +1,130 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2011 OpenWrt.org
+
+#START=98
+
+USE_PROCD=1
+PROG=/usr/sbin/ntpd
+HOTPLUG_SCRIPT=/usr/sbin/ntpd-hotplug
+
+get_dhcp_ntp_servers() {
+	local interfaces="$1"
+	local filter="*"
+	local interface ntpservers ntpserver
+
+	for interface in $interfaces; do
+		[ "$filter" = "*" ] && filter="@.interface='$interface'" || filter="$filter,@.interface='$interface'"
+	done
+
+	ntpservers=$(ubus call network.interface dump | jsonfilter -e "@.interface[$filter]['data']['ntpserver']")
+
+	for ntpserver in $ntpservers; do
+		local duplicate=0
+		local entry
+		for entry in $server; do
+			[ "$ntpserver" = "$entry" ] && duplicate=1
+		done
+		[ "$duplicate" = 0 ] && server="$server $ntpserver"
+	done
+}
+
+validate_ntp_section() {
+	uci_load_validate system timeserver "$1" "$2" \
+		'dhcp_interface:list(string)' \
+		'enable_server:bool:0' \
+		'enabled:bool:1' \
+		'interface:string' \
+		'server:list(host)' \
+		'use_dhcp:bool:1'
+}
+
+start_ntpd_instance() {
+	local peer
+
+	[ "$2" = 0 ] || {
+		echo "validation failed"
+		return 1
+	}
+
+	[ $enabled = 0 ] && return
+
+	[ $use_dhcp = 1 ] && get_dhcp_ntp_servers "$dhcp_interface"
+
+	[ -z "$server" -a "$enable_server" = "0" ] && return
+
+	procd_open_instance
+	procd_set_param command "$PROG" -n -N
+	if [ "$enable_server" = "1" ]; then
+		procd_append_param command -l
+		[ -n "$interface" ] && {
+			local ifname
+
+			network_get_device ifname "$interface" || \
+				ifname="$interface"
+			procd_append_param command -I "$ifname"
+			procd_append_param netdev "$ifname"
+		}
+	fi
+	[ -x "$HOTPLUG_SCRIPT" ] && procd_append_param command -S "$HOTPLUG_SCRIPT"
+	for peer in $server; do
+		procd_append_param command -p $peer
+	done
+#	procd_set_param respawn
+	[ -x /sbin/ujail -a -e /etc/capabilities/ntpd.json ] && {
+		procd_add_jail ntpd ubus
+		procd_add_jail_mount "$HOTPLUG_SCRIPT"
+		procd_add_jail_mount "/usr/share/libubox/jshn.sh"
+		procd_add_jail_mount "/usr/bin/env"
+		procd_add_jail_mount "/usr/bin/jshn"
+		procd_add_jail_mount "/bin/ubus"
+		procd_set_param capabilities /etc/capabilities/ntpd.json
+		procd_set_param user ntp
+		procd_set_param group ntp
+		procd_set_param no_new_privs 1
+	}
+	procd_close_instance
+}
+
+start_service() {
+	. /lib/functions/network.sh
+	validate_ntp_section ntp start_ntpd_instance
+}
+
+service_triggers() {
+	local script name use_dhcp enable_server interface
+
+	script=$(readlink -f "$initscript")
+	name=$(basename ${script:-$initscript})
+
+	procd_add_config_trigger "config.change" "system" /etc/init.d/$name reload
+
+	config_load system
+	config_get use_dhcp ntp use_dhcp 1
+
+	[ $use_dhcp = 1 ] && {
+		local dhcp_interface
+		config_get dhcp_interface ntp dhcp_interface
+
+		if [ -n "$dhcp_interface" ]; then
+			for n in $dhcp_interface; do
+				procd_add_interface_trigger "interface.*" $n /etc/init.d/$name reload
+			done
+		else
+			procd_add_raw_trigger "interface.*" 1000 /etc/init.d/$name reload
+		fi
+	}
+
+	config_get_bool enable_server ntp enable_server 0
+	config_get interface ntp interface
+
+	[ $enable_server -eq 1 ] && [ -n "$interface" ] && {
+		local ifname
+
+		network_get_device ifname "$interface" || \
+			ifname="$interface"
+		procd_add_interface_trigger "interface.*" "$ifname" \
+			/etc/init.d/"$name" reload
+	}
+
+	procd_add_validation validate_ntp_section
+}
diff --git a/package/utils/busybox/patches/120-lto-jobserver.patch b/package/utils/busybox/patches/120-lto-jobserver.patch
new file mode 100644
index 0000000..d4f997e
--- /dev/null
+++ b/package/utils/busybox/patches/120-lto-jobserver.patch
@@ -0,0 +1,27 @@
+--- a/scripts/Kbuild.include
++++ b/scripts/Kbuild.include
+@@ -131,7 +131,7 @@ make-cmd = $(subst \#,\\\#,$(subst $$,$$
+ #
+ if_changed = $(if $(strip $(filter-out $(PHONY),$?)          \
+ 		$(call arg-check, $(cmd_$(1)), $(cmd_$@)) ), \
+-	@set -e; \
++	+@set -e; \
+ 	$(echo-cmd) $(cmd_$(1)); \
+ 	echo 'cmd_$@ := $(make-cmd)' > $(@D)/.$(@F).cmd)
+ 
+@@ -140,7 +140,7 @@ if_changed = $(if $(strip $(filter-out $
+ if_changed_dep = $(if $(strip $(filter-out $(PHONY),$?)  \
+ 		$(filter-out FORCE $(wildcard $^),$^)    \
+ 	$(call arg-check, $(cmd_$(1)), $(cmd_$@)) ),     \
+-	@set -e; \
++	+@set -e; \
+ 	$(echo-cmd) $(cmd_$(1)); \
+ 	scripts/basic/fixdep $(depfile) $@ '$(make-cmd)' > $(@D)/.$(@F).tmp; \
+ 	rm -f $(depfile); \
+@@ -151,5 +151,5 @@ if_changed_dep = $(if $(strip $(filter-o
+ # and if so will execute $(rule_foo)
+ if_changed_rule = $(if $(strip $(filter-out $(PHONY),$?)            \
+ 			$(call arg-check, $(cmd_$(1)), $(cmd_$@)) ),\
+-			@set -e; \
++			+@set -e; \
+ 			$(rule_$(1)))
diff --git a/package/utils/busybox/patches/200-udhcpc_reduce_msgs.patch b/package/utils/busybox/patches/200-udhcpc_reduce_msgs.patch
new file mode 100644
index 0000000..c0f234e
--- /dev/null
+++ b/package/utils/busybox/patches/200-udhcpc_reduce_msgs.patch
@@ -0,0 +1,18 @@
+--- a/networking/udhcp/dhcpc.c
++++ b/networking/udhcp/dhcpc.c
+@@ -722,6 +722,7 @@ static int bcast_or_ucast(struct dhcp_pa
+ static NOINLINE int send_discover(uint32_t requested)
+ {
+ 	struct dhcp_packet packet;
++	static int msgs = 0;
+ 
+ 	/* Fill in: op, htype, hlen, cookie, chaddr fields,
+ 	 * xid field, message type option:
+@@ -736,6 +737,7 @@ static NOINLINE int send_discover(uint32
+ 	 */
+ 	add_client_options(&packet);
+ 
++	if (msgs++ < 3)
+ 	bb_simple_info_msg("broadcasting discover");
+ 	return raw_bcast_from_client_data_ifindex(&packet, INADDR_ANY);
+ }
diff --git a/package/utils/busybox/patches/201-udhcpc_changed_ifindex.patch b/package/utils/busybox/patches/201-udhcpc_changed_ifindex.patch
new file mode 100644
index 0000000..a4bda99
--- /dev/null
+++ b/package/utils/busybox/patches/201-udhcpc_changed_ifindex.patch
@@ -0,0 +1,15 @@
+--- a/networking/udhcp/dhcpc.c
++++ b/networking/udhcp/dhcpc.c
+@@ -1384,6 +1384,12 @@ int udhcpc_main(int argc UNUSED_PARAM, c
+ 		struct pollfd pfds[2];
+ 		struct dhcp_packet packet;
+ 
++		/* When running on a bridge, the ifindex may have changed (e.g. if
++		 * member interfaces were added/removed or if the status of the
++		 * bridge changed).
++		 * Workaround: refresh it here before processing the next packet */
++		udhcp_read_interface(client_data.interface, &client_data.ifindex, NULL, client_data.client_mac);
++
+ 		//bb_error_msg("sockfd:%d, listen_mode:%d", client_data.sockfd, client_data.listen_mode);
+ 
+ 		/* Was opening raw or udp socket here
diff --git a/package/utils/busybox/patches/210-add_netmsg_util.patch b/package/utils/busybox/patches/210-add_netmsg_util.patch
new file mode 100644
index 0000000..d7b2ae7
--- /dev/null
+++ b/package/utils/busybox/patches/210-add_netmsg_util.patch
@@ -0,0 +1,79 @@
+--- /dev/null
++++ b/networking/netmsg.c
+@@ -0,0 +1,76 @@
++/*
++ * Copyright (C) 2006 Felix Fietkau <nbd@nbd.name>
++ *
++ * This is free software, licensed under the GNU General Public License v2.
++ */
++
++//config:config NETMSG
++//config:	bool "netmsg"
++//config:	default n
++//config:	help
++//config:	  simple program for sending udp broadcast messages
++
++//applet:IF_NETMSG(APPLET(netmsg, BB_DIR_BIN, BB_SUID_REQUIRE))
++
++//kbuild:lib-$(CONFIG_NETMSG) += netmsg.o
++
++//usage:#define netmsg_trivial_usage NOUSAGE_STR
++//usage:#define netmsg_full_usage ""
++
++#include <sys/types.h>
++#include <sys/socket.h>
++#include <netinet/in.h>
++#include <netdb.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include "busybox.h"
++
++#ifndef CONFIG_NETMSG
++int main(int argc, char **argv)
++#else
++int netmsg_main(int argc, char **argv)
++#endif
++{
++	int s;
++	struct sockaddr_in addr;
++	int optval = 1;
++	unsigned char buf[1001];
++
++	if (argc != 3) {
++		fprintf(stderr, "usage: %s <ip> \"<message>\"\n", argv[0]);
++		exit(1);
++	}
++
++	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
++		perror("Opening socket");
++		exit(1);
++	}
++
++	memset(&addr, 0, sizeof(addr));
++	addr.sin_family = AF_INET;
++	addr.sin_addr.s_addr = inet_addr(argv[1]);
++	addr.sin_port = htons(0x1337);
++
++	memset(buf, 0, 1001);
++	buf[0] = 0xde;
++	buf[1] = 0xad;
++
++	strncpy(buf + 2, argv[2], 998);
++
++	if (setsockopt (s, SOL_SOCKET, SO_BROADCAST, (caddr_t) &optval, sizeof (optval)) < 0) {
++		perror("setsockopt()");
++		goto fail;
++	}
++
++	if (sendto(s, buf, 1001, 0, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
++		perror("sendto()");
++		goto fail;
++	}
++
++	return 0;
++
++fail:
++	close(s);
++	exit(1);
++}
diff --git a/package/utils/busybox/patches/220-add_lock_util.patch b/package/utils/busybox/patches/220-add_lock_util.patch
new file mode 100644
index 0000000..579b705
--- /dev/null
+++ b/package/utils/busybox/patches/220-add_lock_util.patch
@@ -0,0 +1,158 @@
+--- /dev/null
++++ b/miscutils/lock.c
+@@ -0,0 +1,155 @@
++/*
++ * Copyright (C) 2006 Felix Fietkau <nbd@nbd.name>
++ *
++ * This is free software, licensed under the GNU General Public License v2.
++ */
++
++//config:config LOCK
++//config:	bool "lock"
++//config:	default n
++//config:	help
++//config:	  Small utility for using locks in scripts
++
++//applet:IF_LOCK(APPLET(lock, BB_DIR_BIN, BB_SUID_DROP))
++
++//kbuild:lib-$(CONFIG_LOCK) += lock.o
++
++//usage:#define lock_trivial_usage NOUSAGE_STR
++//usage:#define lock_full_usage ""
++
++#include <sys/types.h>
++#include <sys/file.h>
++#include <sys/stat.h>
++#include <signal.h>
++#include <fcntl.h>
++#include <unistd.h>
++#include <stdio.h>
++#include "busybox.h"
++
++static int unlock = 0;
++static int shared = 0;
++static int waitonly = 0;
++static int try_lock = 0;
++static int fd;
++static char *file;
++
++static void usage(char *name)
++{
++	fprintf(stderr, "Usage: %s [-suw] <filename>\n"
++	                "	-s	Use shared locking\n"
++	                "	-u	Unlock\n"
++	                "	-w	Wait for the lock to become free, don't acquire lock\n"
++			"	-n	Don't wait for the lock to become free. Fail with exit code\n"
++					"\n", name);
++	exit(1);
++}
++
++static void exit_unlock(int sig)
++{
++	flock(fd, LOCK_UN);
++	exit(0);
++}
++
++static int do_unlock(void)
++{
++	FILE *f;
++	int i;
++
++	if ((f = fopen(file, "r")) == NULL)
++		return 0;
++
++	fscanf(f, "%d", &i);
++	if (i > 0)
++		kill(i, SIGTERM);
++
++	fclose(f);
++
++	return 0;
++}
++
++static int do_lock(void)
++{
++	pid_t pid;
++	int flags;
++	char pidstr[12];
++
++	if ((fd = open(file, O_RDWR | O_CREAT | O_EXCL, 0700)) < 0) {
++		if ((fd = open(file, O_RDWR)) < 0) {
++			fprintf(stderr, "Can't open %s\n", file);
++			return 1;
++		}
++	}
++
++	flags = shared ? LOCK_SH : LOCK_EX;
++	flags |= try_lock ? LOCK_NB : 0;
++
++	if (flock(fd, flags) < 0) {
++		fprintf(stderr, "Can't lock %s\n", file);
++		return 1;
++	}
++
++	pid = fork();
++
++	if (pid < 0)
++		return -1;
++
++	if (pid == 0) {
++		signal(SIGKILL, exit_unlock);
++		signal(SIGTERM, exit_unlock);
++		signal(SIGINT, exit_unlock);
++		if (waitonly)
++			exit_unlock(0);
++		else
++			while (1)
++				sleep(1);
++	} else {
++		if (!waitonly) {
++			lseek(fd, 0, SEEK_SET);
++			ftruncate(fd, 0);
++			snprintf(pidstr, sizeof(pidstr), "%d\n", pid);
++			write(fd, pidstr, strlen(pidstr));
++			close(fd);
++		}
++
++		return 0;
++	}
++	return 0;
++}
++
++int lock_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
++int lock_main(int argc, char **argv)
++{
++	char **args = &argv[1];
++	int c = argc - 1;
++
++	while ((*args != NULL) && (*args)[0] == '-') {
++		char *ch = *args;
++		while (*(++ch) > 0) {
++			switch(*ch) {
++				case 'w':
++					waitonly = 1;
++					break;
++				case 's':
++					shared = 1;
++					break;
++				case 'u':
++					unlock = 1;
++					break;
++				case 'n':
++					try_lock = 1;
++					break;
++			}
++		}
++		c--;
++		args++;
++	}
++
++	if (c != 1)
++		usage(argv[0]);
++
++	file = *args;
++	if (unlock)
++		return do_unlock();
++	else
++		return do_lock();
++}
diff --git a/package/utils/busybox/patches/270-libbb_make_unicode_printable.patch b/package/utils/busybox/patches/270-libbb_make_unicode_printable.patch
new file mode 100644
index 0000000..0b682dc
--- /dev/null
+++ b/package/utils/busybox/patches/270-libbb_make_unicode_printable.patch
@@ -0,0 +1,20 @@
+--- a/libbb/printable_string.c
++++ b/libbb/printable_string.c
+@@ -28,8 +28,6 @@ const char* FAST_FUNC printable_string2(
+ 		}
+ 		if (c < ' ')
+ 			break;
+-		if (c >= 0x7f)
+-			break;
+ 		s++;
+ 	}
+ 
+@@ -42,7 +40,7 @@ const char* FAST_FUNC printable_string2(
+ 			unsigned char c = *d;
+ 			if (c == '\0')
+ 				break;
+-			if (c < ' ' || c >= 0x7f)
++			if (c < ' ')
+ 				*d = '?';
+ 			d++;
+ 		}
diff --git a/package/utils/busybox/patches/301-ip-link-fix-netlink-msg-size.patch b/package/utils/busybox/patches/301-ip-link-fix-netlink-msg-size.patch
new file mode 100644
index 0000000..f4c0a80
--- /dev/null
+++ b/package/utils/busybox/patches/301-ip-link-fix-netlink-msg-size.patch
@@ -0,0 +1,11 @@
+--- a/networking/libiproute/iplink.c
++++ b/networking/libiproute/iplink.c
+@@ -683,7 +683,7 @@ static int do_add_or_delete(char **argv,
+ 	}
+ 	xrtnl_open(&rth);
+ 	ll_init_map(&rth);
+-	if (type_str) {
++	if (type_str && rtm == RTM_NEWLINK) {
+ 		struct rtattr *linkinfo = NLMSG_TAIL(&req.n);
+ 
+ 		addattr_l(&req.n, sizeof(req), IFLA_LINKINFO, NULL, 0);
diff --git a/package/utils/busybox/patches/500-move-traceroute-applets-to-bin.patch b/package/utils/busybox/patches/500-move-traceroute-applets-to-bin.patch
new file mode 100644
index 0000000..0389eed
--- /dev/null
+++ b/package/utils/busybox/patches/500-move-traceroute-applets-to-bin.patch
@@ -0,0 +1,13 @@
+--- a/networking/traceroute.c
++++ b/networking/traceroute.c
+@@ -236,8 +236,8 @@
+ //config:	depends on TRACEROUTE || TRACEROUTE6
+ 
+ /* Needs socket(AF_INET, SOCK_RAW, IPPROTO_ICMP), therefore BB_SUID_MAYBE: */
+-//applet:IF_TRACEROUTE(APPLET(traceroute, BB_DIR_USR_BIN, BB_SUID_MAYBE))
+-//applet:IF_TRACEROUTE6(APPLET(traceroute6, BB_DIR_USR_BIN, BB_SUID_MAYBE))
++//applet:IF_TRACEROUTE(APPLET(traceroute, BB_DIR_BIN, BB_SUID_MAYBE))
++//applet:IF_TRACEROUTE6(APPLET(traceroute6, BB_DIR_BIN, BB_SUID_MAYBE))
+ 
+ //kbuild:lib-$(CONFIG_TRACEROUTE) += traceroute.o
+ //kbuild:lib-$(CONFIG_TRACEROUTE6) += traceroute.o
diff --git a/package/utils/busybox/patches/510-move-passwd-applet-to-bin.patch b/package/utils/busybox/patches/510-move-passwd-applet-to-bin.patch
new file mode 100644
index 0000000..7dc2cd3
--- /dev/null
+++ b/package/utils/busybox/patches/510-move-passwd-applet-to-bin.patch
@@ -0,0 +1,11 @@
+--- a/loginutils/passwd.c
++++ b/loginutils/passwd.c
+@@ -23,7 +23,7 @@
+ //config:	With this option passwd will refuse new passwords which are "weak".
+ 
+ //applet:/* Needs to be run by root or be suid root - needs to change /etc/{passwd,shadow}: */
+-//applet:IF_PASSWD(APPLET(passwd, BB_DIR_USR_BIN, BB_SUID_REQUIRE))
++//applet:IF_PASSWD(APPLET(passwd, BB_DIR_BIN, BB_SUID_REQUIRE))
+ 
+ //kbuild:lib-$(CONFIG_PASSWD) += passwd.o
+ 
diff --git a/package/utils/busybox/patches/520-loginutils-handle-crypt-failures.patch b/package/utils/busybox/patches/520-loginutils-handle-crypt-failures.patch
new file mode 100644
index 0000000..91340d4
--- /dev/null
+++ b/package/utils/busybox/patches/520-loginutils-handle-crypt-failures.patch
@@ -0,0 +1,53 @@
+--- a/loginutils/chpasswd.c
++++ b/loginutils/chpasswd.c
+@@ -89,6 +89,11 @@ int chpasswd_main(int argc UNUSED_PARAM,
+ 
+ 			crypt_make_pw_salt(salt, algo);
+ 			free_me = pass = pw_encrypt(pass, salt, 0);
++
++			if (pass[0] == 0) {
++				free(free_me);
++				bb_perror_msg_and_die("password encryption failed");
++			}
+ 		}
+ 
+ 		/* This is rather complex: if user is not found in /etc/shadow,
+--- a/loginutils/cryptpw.c
++++ b/loginutils/cryptpw.c
+@@ -87,7 +87,7 @@ int cryptpw_main(int argc UNUSED_PARAM,
+ 	/* Supports: cryptpw -m sha256 PASS 'rounds=999999999$SALT' */
+ 	char salt[MAX_PW_SALT_LEN + sizeof("rounds=999999999$")];
+ 	char *salt_ptr;
+-	char *password;
++	char *password, *hash;
+ 	const char *opt_m, *opt_S;
+ 	int fd;
+ 
+@@ -132,8 +132,12 @@ int cryptpw_main(int argc UNUSED_PARAM,
+ 		/* may still be NULL on EOF/error */
+ 	}
+ 
+-	if (password)
+-		puts(pw_encrypt(password, salt, 1));
++	if (password) {
++		hash = pw_encrypt(password, salt, 1);
++		if (hash[0] == 0)
++			bb_perror_msg_and_die("password encryption failed");
++		puts(hash);
++	}
+ 
+ 	return EXIT_SUCCESS;
+ }
+--- a/loginutils/passwd.c
++++ b/loginutils/passwd.c
+@@ -187,6 +187,10 @@ int passwd_main(int argc UNUSED_PARAM, c
+ 		if (!newp) {
+ 			logmode = LOGMODE_STDIO;
+ 			bb_error_msg_and_die("password for %s is unchanged", name);
++		} else if (newp[0] == 0) {
++			logmode = LOGMODE_STDIO;
++			free(newp);
++			bb_perror_msg_and_die("password encryption failed");
+ 		}
+ 	} else if (opt & OPT_lock) {
+ 		if (!c)
diff --git a/package/utils/busybox/patches/530-nslookup-ensure-unique-transaction-IDs-for-the-DNS-queries.patch b/package/utils/busybox/patches/530-nslookup-ensure-unique-transaction-IDs-for-the-DNS-queries.patch
new file mode 100644
index 0000000..caa5ee7
--- /dev/null
+++ b/package/utils/busybox/patches/530-nslookup-ensure-unique-transaction-IDs-for-the-DNS-queries.patch
@@ -0,0 +1,42 @@
+From: Uwe Kleine-König <uwe@kleine-koenig.org>
+Date: Sat, 8 Oct 2022 19:22:52 +0200
+Subject: [PATCH] nslookup: ensure unique transaction IDs for the DNS queries
+
+The transaction IDs generated by res_mkquery() for both glibc and musl only
+depends on the state of the monotonic clock.
+For some machines (here: a TP-Link RE200 powered by a MediaTek MT7620A)
+the monotonic clock has a coarse resolution (here: 20 µs) and it can happen
+that the requests for A and AAAA share the same transaction ID.
+
+In that case the mapping from received responses to the sent queries
+doesn't work and name resolution fails as follows:
+
+        # /bin/busybox nslookup heise.de
+        Server:         127.0.0.1
+        Address:        127.0.0.1:53
+
+        Non-authoritative answer:
+        Name:   heise.de
+        Address: 193.99.144.80
+
+        *** Can't find heise.de: No answer
+
+because the AAAA reply is dropped as a duplicate reply to the A query.
+
+To prevent this make sure the transaction IDs are unique.
+
+Forwarded: http://lists.busybox.net/pipermail/busybox/2022-October/089911.html
+---
+--- a/networking/nslookup.c
++++ b/networking/nslookup.c
+@@ -978,6 +978,10 @@ int nslookup_main(int argc UNUSED_PARAM,
+ 		}
+ 	}
+ 
++	/* Ensure the Transaction IDs are unique */
++	for (rc = 1; rc < G.query_count; rc++)
++		G.query[rc].query[1] = G.query[rc - 1].query[1] + 1;
++
+ 	for (rc = 0; rc < G.serv_count;) {
+ 		int c;
+ 
diff --git a/package/utils/busybox/patches/540-ignore-SIGQUIT-to-avoid-coredump.patch b/package/utils/busybox/patches/540-ignore-SIGQUIT-to-avoid-coredump.patch
new file mode 100644
index 0000000..31618bf
--- /dev/null
+++ b/package/utils/busybox/patches/540-ignore-SIGQUIT-to-avoid-coredump.patch
@@ -0,0 +1,11 @@
+--- a/shell/ash.c
++++ b/shell/ash.c
+@@ -10079,7 +10079,7 @@ execcmd(int argc UNUSED_PARAM, char **ar
+ 		 * SIGQUIT is still set to IGN. Fix it:
+ 		 */
+ 		shlvl++;
+-		setsignal(SIGQUIT);
++		/*setsignal(SIGQUIT); - avoid coredump after "ctrl+\" or executing "kill -3" in shell */
+ 		/*setsignal(SIGTERM); - unnecessary because of iflag=0 */
+ 		/*setsignal(SIGTSTP); - unnecessary because of mflag=0 */
+ 		/*setsignal(SIGTTOU); - unnecessary because of mflag=0 */
diff --git a/package/utils/busybox/patches/600-get-seuser-from-username.patch b/package/utils/busybox/patches/600-get-seuser-from-username.patch
new file mode 100644
index 0000000..7744f1c
--- /dev/null
+++ b/package/utils/busybox/patches/600-get-seuser-from-username.patch
@@ -0,0 +1,34 @@
+--- a/loginutils/login.c
++++ b/loginutils/login.c
+@@ -183,13 +183,17 @@ static void die_if_nologin(void)
+ static void initselinux(char *username, char *full_tty,
+ 						security_context_t *user_sid)
+ {
++	char *seuser = NULL, *level = NULL;
+ 	security_context_t old_tty_sid, new_tty_sid;
+ 
+ 	if (!is_selinux_enabled())
+ 		return;
+ 
+-	if (get_default_context(username, NULL, user_sid)) {
+-		bb_error_msg_and_die("can't get SID for %s", username);
++	if (getseuserbyname(username, &seuser, &level)) {
++		bb_error_msg_and_die("can't get seuser for %s", username);
++	}
++	if (get_default_context(seuser, NULL, user_sid)) {
++		bb_error_msg_and_die("can't get SID for %s", seuser);
+ 	}
+ 	if (getfilecon(full_tty, &old_tty_sid) < 0) {
+ 		bb_perror_msg_and_die("getfilecon(%s) failed", full_tty);
+@@ -201,6 +205,11 @@ static void initselinux(char *username,
+ 	if (setfilecon(full_tty, new_tty_sid) != 0) {
+ 		bb_perror_msg_and_die("chsid(%s, %s) failed", full_tty, new_tty_sid);
+ 	}
++
++	if (ENABLE_FEATURE_CLEAN_UP) {
++		free(seuser);
++		free(level);
++	}
+ }
+ #endif
+ 
diff --git a/package/utils/busybox/patches/601-fix_termios_configuration_missing.patch b/package/utils/busybox/patches/601-fix_termios_configuration_missing.patch
new file mode 100644
index 0000000..9f2d9b6
--- /dev/null
+++ b/package/utils/busybox/patches/601-fix_termios_configuration_missing.patch
@@ -0,0 +1,27 @@
+--- a/libbb/lineedit.c
++++ b/libbb/lineedit.c
+@@ -2467,6 +2467,7 @@ int FAST_FUNC read_line_input(line_input
+ #endif
+ 	struct termios initial_settings;
+ 	struct termios new_settings;
++	struct termios tmp_settings;
+ 	char read_key_buffer[KEYCODE_BUFFER_SIZE];
+ 
+ 	INIT_S();
+@@ -3006,7 +3007,15 @@ int FAST_FUNC read_line_input(line_input
+ #endif
+ 
+ 	/* restore initial_settings */
+-	tcsetattr_stdin_TCSANOW(&initial_settings);
++	if (tcgetattr(STDIN_FILENO, &tmp_settings) < 0){
++		tcsetattr_stdin_TCSANOW(&initial_settings);
++	}else{
++		tmp_settings.c_lflag |= (ICANON | ECHO | ECHONL | ISIG);
++		tmp_settings.c_cc[VMIN] = initial_settings.c_cc[VMIN];
++		tmp_settings.c_cc[VTIME] = initial_settings.c_cc[VTIME];
++		tcsetattr_stdin_TCSANOW(&tmp_settings);
++	}
++
+ #if ENABLE_FEATURE_EDITING_WINCH
+ 	/* restore SIGWINCH handler */
+ 	sigaction_set(SIGWINCH, &S.SIGWINCH_handler);
diff --git a/package/utils/busybox/selinux.config b/package/utils/busybox/selinux.config
new file mode 100644
index 0000000..ef20155
--- /dev/null
+++ b/package/utils/busybox/selinux.config
@@ -0,0 +1,15 @@
+CONFIG_SELINUX=y
+CONFIG_FEATURE_TAR_SELINUX=y
+CONFIG_CHCON=y
+CONFIG_GETENFORCE=y
+CONFIG_GETSEBOOL=y
+CONFIG_LOAD_POLICY=y
+CONFIG_MATCHPATHCON=y
+CONFIG_RUNCON=y
+CONFIG_SELINUXENABLED=y
+CONFIG_SESTATUS=y
+CONFIG_SETFILES=y
+CONFIG_FEATURE_SETFILES_CHECK_OPTION=y
+CONFIG_RESTORECON=y
+CONFIG_SETSEBOOL=y
+CONFIG_SETENFORCE=y
diff --git a/package/utils/bzip2/Makefile b/package/utils/bzip2/Makefile
new file mode 100644
index 0000000..7ae089f
--- /dev/null
+++ b/package/utils/bzip2/Makefile
@@ -0,0 +1,110 @@
+#
+# Copyright (C) 2007-2008 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=bzip2
+PKG_VERSION:=1.0.8
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://sourceware.org/pub/bzip2
+PKG_HASH:=ab5a03176ee106d3f0fa90e381da478ddae405918153cca248e682cd0c4a2269
+
+PKG_MAINTAINER:=Steven Barth <cyrus@openwrt.org>
+PKG_LICENSE:=bzip2-1.0.8
+PKG_LICENSE_FILES:=LICENSE
+PKG_CPE_ID:=cpe:/a:bzip:bzip2
+
+include $(INCLUDE_DIR)/host-build.mk
+include $(INCLUDE_DIR)/package.mk
+
+define Package/bzip2/Default
+  SUBMENU:=Compression
+  URL:=https://sourceware.org/bzip2/
+endef
+
+define Package/libbz2
+$(call Package/bzip2/Default)
+  SECTION:=libs
+  CATEGORY:=Libraries
+  DEPENDS:=
+  TITLE:=bzip2 library.
+  ABI_VERSION:=1.0
+endef
+
+define Package/libbz2/description
+	bzip2 is a freely available, patent free, high-quality
+	data compressor. This packages provides libbz2 library.
+endef
+
+define Package/bzip2
+$(call Package/bzip2/Default)
+  SECTION:=utils
+  CATEGORY:=Utilities
+  DEPENDS:=+libbz2
+  TITLE:=bzip2 is a compression utility.
+endef
+
+define Package/bzip2/description
+	bzip2 is a freely available, patent free, high-quality
+	data compressor. This package provides the binary.
+endef
+
+TARGET_CFLAGS += \
+	$(FPIC)
+
+CONFIGURE_ARGS += --prefix=/usr
+
+MAKE_FLAGS += \
+	-f Makefile-libbz2_so \
+	CFLAGS="$(TARGET_CFLAGS)" \
+	LDFLAGS="$(TARGET_LDFLAGS)" \
+	all
+
+define Build/InstallDev
+	$(INSTALL_DIR) $(1)/usr/include
+	$(CP) $(PKG_BUILD_DIR)/bzlib.h $(1)/usr/include/
+	$(INSTALL_DIR) $(1)/usr/lib
+	$(CP) $(PKG_BUILD_DIR)/libbz2.so.$(PKG_VERSION) $(1)/usr/lib/
+	$(LN) libbz2.so.$(PKG_VERSION) $(1)/usr/lib/libbz2.so.1.0
+	$(LN) libbz2.so.$(PKG_VERSION) $(1)/usr/lib/libbz2.so
+endef
+
+define Package/libbz2/install
+	$(INSTALL_DIR) $(1)/usr/lib/
+	$(CP) $(PKG_BUILD_DIR)/libbz2.so.$(PKG_VERSION) $(1)/usr/lib/
+	$(LN) libbz2.so.$(PKG_VERSION) $(1)/usr/lib/libbz2.so.1.0
+endef
+
+define Package/bzip2/install
+	$(INSTALL_DIR) $(1)/usr/bin/
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/bzip2-shared $(1)/usr/bin/bzip2
+	$(INSTALL_DIR) $(1)/bin/
+	$(LN) ../usr/bin/bzip2 $(1)/bin/bzip2
+endef
+
+HOST_CFLAGS += \
+	$(FPIC)
+
+HOST_MAKE_FLAGS+= \
+	CFLAGS="$(HOST_CFLAGS)" \
+	LDFLAGS="$(HOST_LDFLAGS)" \
+	all
+
+HOST_CONFIGURE_ARGS+= \
+	--prefix=$(STAGING_DIR_HOSTPKG)
+
+define Host/Install
+	$(INSTALL_DIR) $(STAGING_DIR_HOSTPKG)/bin/
+	$(MAKE) -C $(HOST_BUILD_DIR) PREFIX=$(STAGING_DIR_HOSTPKG)/ install
+endef
+
+$(eval $(call HostBuild))
+
+$(eval $(call BuildPackage,libbz2))
+$(eval $(call BuildPackage,bzip2))
diff --git a/package/utils/bzip2/patches/020-no-utime.patch b/package/utils/bzip2/patches/020-no-utime.patch
new file mode 100644
index 0000000..d0cd4f0
--- /dev/null
+++ b/package/utils/bzip2/patches/020-no-utime.patch
@@ -0,0 +1,27 @@
+--- a/bzip2.c
++++ b/bzip2.c
+@@ -69,7 +69,6 @@
+ #if BZ_UNIX
+ #   include <fcntl.h>
+ #   include <sys/types.h>
+-#   include <utime.h>
+ #   include <unistd.h>
+ #   include <sys/stat.h>
+ #   include <sys/times.h>
+@@ -1051,12 +1050,12 @@ void applySavedTimeInfoToOutputFile ( Ch
+ {
+ #  if BZ_UNIX
+    IntNative      retVal;
+-   struct utimbuf uTimBuf;
++   struct timespec uTimBuf[2] = {};
+ 
+-   uTimBuf.actime = fileMetaInfo.st_atime;
+-   uTimBuf.modtime = fileMetaInfo.st_mtime;
++   uTimBuf[0].tv_sec = fileMetaInfo.st_atime;
++   uTimBuf[1].tv_sec = fileMetaInfo.st_mtime;
+ 
+-   retVal = utime ( dstName, &uTimBuf );
++   retVal = utimensat ( AT_FDCWD, dstName, uTimBuf , 0 );
+    ERROR_IF_NOT_ZERO ( retVal );
+ #  endif
+ }
diff --git a/package/utils/bzip2/patches/021-fix-LDFLAGS.patch b/package/utils/bzip2/patches/021-fix-LDFLAGS.patch
new file mode 100644
index 0000000..7929d9a
--- /dev/null
+++ b/package/utils/bzip2/patches/021-fix-LDFLAGS.patch
@@ -0,0 +1,11 @@
+--- a/Makefile-libbz2_so
++++ b/Makefile-libbz2_so
+@@ -35,7 +35,7 @@ OBJS= blocksort.o  \
+       bzlib.o
+ 
+ all: $(OBJS)
+-	$(CC) -shared -Wl,-soname -Wl,libbz2.so.1.0 -o libbz2.so.1.0.8 $(OBJS)
++	$(CC) -shared -Wl,-soname -Wl,libbz2.so.1.0 $(LDFLAGS) -o libbz2.so.1.0.8 $(OBJS)
+ 	$(CC) $(CFLAGS) -o bzip2-shared bzip2.c libbz2.so.1.0.8
+ 	rm -f libbz2.so.1.0
+ 	ln -s libbz2.so.1.0.8 libbz2.so.1.0
diff --git a/package/utils/checkpolicy/Makefile b/package/utils/checkpolicy/Makefile
new file mode 100644
index 0000000..4ebf97b
--- /dev/null
+++ b/package/utils/checkpolicy/Makefile
@@ -0,0 +1,52 @@
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=checkpolicy
+PKG_VERSION:=3.5
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://github.com/SELinuxProject/selinux/releases/download/$(PKG_VERSION)
+PKG_HASH:=7aa48ab2222a0b9881111d6d7f70c3014d3d9338827d9e02df105a68c0df5dbc
+PKG_INSTALL:=1
+PKG_BUILD_DEPENDS:=libselinux
+HOST_BUILD_DEPENDS:=libselinux/host
+
+PKG_MAINTAINER:=Thomas Petazzoni <thomas.petazzoni@bootlin.com>
+PKG_CPE_ID:=cpe:/a:selinuxproject:checkpolicy
+PKG_LICENSE:=GPL-2.0-or-later
+PKG_LICENSE_FILES:=COPYING
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/checkpolicy
+  SECTION:=utils
+  CATEGORY:=Utilities
+  TITLE:=SELinux policy compiler
+  URL:=http://selinuxproject.org/page/Main_Page
+endef
+
+define Package/checkpolicy/description
+	checkpolicy is the SELinux policy compiler. It uses libsepol
+	to generate the binary policy. checkpolicy uses the static
+	libsepol since it deals with low level details of the policy
+	that have not been encapsulated/abstracted by a proper
+	shared library interface.
+endef
+
+include $(INCLUDE_DIR)/host-build.mk
+
+HOST_MAKE_FLAGS += \
+	PREFIX=$(STAGING_DIR_HOSTPKG)
+
+define Package/checkpolicy/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(CP) $(PKG_INSTALL_DIR)/usr/bin/* $(1)/usr/bin/
+endef
+
+$(eval $(call HostBuild))
+$(eval $(call BuildPackage,checkpolicy))
diff --git a/package/utils/ct-bugcheck/Makefile b/package/utils/ct-bugcheck/Makefile
new file mode 100644
index 0000000..d8b35df
--- /dev/null
+++ b/package/utils/ct-bugcheck/Makefile
@@ -0,0 +1,52 @@
+#
+# Copyright (C) 2016 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=ct-bugcheck
+PKG_RELEASE:=2016.07.21
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/ct-bugcheck
+  SECTION:=utils
+  CATEGORY:=Utilities
+  TITLE:=Bug checking and reporting utility
+  VERSION:=$(PKG_RELEASE)
+  MAINTAINER:=Ben Greear <greearb@candelatech.com>
+endef
+
+define Package/ct-bugcheck/description
+  Scripts to check for bugs (like firmware crashes) and package them for reporting.
+  Currently this script only checks for ath10k firmware crashes.
+  Once installed, you can enable this tool by creating a file called
+  /etc/config/bugcheck with the following contents:
+ DO_BUGCHECK=1
+ export DO_BUGCHECK
+
+endef
+
+define Build/Prepare
+	$(CP) src/bugcheck.sh $(PKG_BUILD_DIR)/
+	$(CP) src/bugchecker.sh $(PKG_BUILD_DIR)/
+	$(CP) src/bugcheck.initd $(PKG_BUILD_DIR)/
+endef
+
+define Build/Compile
+	true
+endef
+
+define Package/ct-bugcheck/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(INSTALL_DIR) $(1)/etc/init.d
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/bugcheck.sh $(1)/usr/bin/
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/bugchecker.sh $(1)/usr/bin/
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/bugcheck.initd $(1)/etc/init.d/bugcheck
+endef
+
+$(eval $(call BuildPackage,ct-bugcheck))
diff --git a/package/utils/ct-bugcheck/src/bugcheck.initd b/package/utils/ct-bugcheck/src/bugcheck.initd
new file mode 100644
index 0000000..b97a415
--- /dev/null
+++ b/package/utils/ct-bugcheck/src/bugcheck.initd
@@ -0,0 +1,16 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2016 OpenWrt.org
+
+START=99
+
+USE_PROCD=1
+PROG=/usr/bin/bugchecker.sh
+
+# To actually make bugchecker.sh run, see comments
+# at top of its file.
+
+start_service () {
+        procd_open_instance
+        procd_set_param command "$PROG"
+        procd_close_instance
+}
diff --git a/package/utils/ct-bugcheck/src/bugcheck.sh b/package/utils/ct-bugcheck/src/bugcheck.sh
new file mode 100755
index 0000000..3ee4720
--- /dev/null
+++ b/package/utils/ct-bugcheck/src/bugcheck.sh
@@ -0,0 +1,115 @@
+#!/bin/sh
+
+# Check for ath10k (and maybe other) bugs, package them up,
+# and let user know what to do with them.
+
+TMPLOC=/tmp
+CRASHDIR=$TMPLOC/bugcheck
+FOUND_BUG=0
+
+# set -x
+
+bugcheck_generic()
+{
+    echo "OpenWrt crashlog report" > $CRASHDIR/info.txt
+    date >> $CRASHDIR/info.txt
+    echo >> $CRASHDIR/info.txt
+    echo "uname" >> $CRASHDIR/info.txt
+    uname -a >> $CRASHDIR/info.txt
+    echo >> $CRASHDIR/info.txt
+    echo "os-release" >> $CRASHDIR/info.txt
+    cat /etc/os-release >> $CRASHDIR/info.txt
+    echo >> $CRASHDIR/info.txt
+    echo "os-release" >> $CRASHDIR/info.txt
+    cat /etc/os-release >> $CRASHDIR/info.txt
+    echo >> $CRASHDIR/info.txt
+    echo "dmesg output" >> $CRASHDIR/info.txt
+    dmesg >> $CRASHDIR/info.txt
+    if [ -x /usr/bin/lspci ]
+	then
+	echo >> $CRASHDIR/info.txt
+	echo "lspci" >> $CRASHDIR/info.txt
+	lspci >> $CRASHDIR/info.txt
+    fi
+    echo >> $CRASHDIR/info.txt
+    echo "cpuinfo" >> $CRASHDIR/info.txt
+    cat /proc/cpuinfo >> $CRASHDIR/info.txt
+    echo >> $CRASHDIR/info.txt
+    echo "meminfo" >> $CRASHDIR/info.txt
+    cat /proc/cpuinfo >> $CRASHDIR/info.txt
+    echo >> $CRASHDIR/info.txt
+    echo "cmdline" >> $CRASHDIR/info.txt
+    cat /proc/cmdline >> $CRASHDIR/info.txt
+    echo >> $CRASHDIR/info.txt
+    echo "lsmod" >> $CRASHDIR/info.txt
+    lsmod >> $CRASHDIR/info.txt
+}
+
+roll_crashes()
+{
+    # Roll any existing crashes
+    if [ -d $CRASHDIR ]
+	then
+	if [ -d $CRASHDIR.1 ]
+	    then
+	    rm -fr $CRASHDIR.1
+	fi
+	mv $CRASHDIR $CRASHDIR.1
+    fi
+
+    # Prepare location
+    mkdir -p $CRASHDIR
+}
+
+# ath10k, check debugfs entries.
+for i in /sys/kernel/debug/ieee80211/*/ath10k/fw_crash_dump
+do
+  #echo "Checking $i"
+  if cat $i > $TMPLOC/ath10k_crash.bin 2>&1
+      then
+      FOUND_BUG=1
+
+      #echo "Found ath10k crash data in $i"
+      roll_crashes
+
+      ADIR=${i/fw_crash_dump/}
+
+      CTFW=0
+      if grep -- -ct- $TMPLOC/ath10k_crash.bin > /dev/null 2>&1
+	  then
+	  CTFW=1
+      fi
+
+      echo "Send bug reports to:" > $CRASHDIR/report_to.txt
+      if [ -f $ADIR/ct_special -o $CTFW == "1" ]
+	  then
+	  # Looks like this is CT firmware or driver...
+	  echo "greearb@candelatech.com" >> $CRASHDIR/report_to.txt
+	  echo "and/or report or check for duplicates here:" >> $CRASHDIR/report_to.txt
+	  echo "https://github.com/greearb/ath10k-ct/issues" >> $CRASHDIR/report_to.txt
+      else
+	  # Not sure who would want these bug reports for upstream...
+	  echo "https://openwrt.org/" >> $CRASHDIR/report_to.txt
+      fi
+      echo >> $CRASHDIR/report_to.txt
+      echo "Please attach all files in this directory to bug reports." >> $CRASHDIR/report_to.txt
+
+      mv $TMPLOC/ath10k_crash.bin $CRASHDIR
+
+      # Add any more ath10k specific stuff here.
+
+      # And call generic bug reporting logic
+      bugcheck_generic
+  fi
+done
+
+if [ $FOUND_BUG == "1" ]
+    then
+    # Notify LUCI somehow?
+    echo "bugcheck.sh found an issue to be reported" > /dev/kmsg
+    echo "See $CRASHDIR for details on how to report this" > /dev/kmsg
+    # Let calling code know something was wrong.
+    exit 1
+fi
+
+exit 0
diff --git a/package/utils/ct-bugcheck/src/bugchecker.sh b/package/utils/ct-bugcheck/src/bugchecker.sh
new file mode 100755
index 0000000..be305af
--- /dev/null
+++ b/package/utils/ct-bugcheck/src/bugchecker.sh
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+# Periodically call bugcheck.sh script
+
+CHECKER=bugcheck.sh
+SLEEPFOR=60
+
+DO_BUGCHECK=0
+
+# So, to enable this, you create an /etc/config/bugcheck file
+# with contents like:
+#  DO_BUGCHECK=1
+#  export DO_BUGCHECK
+
+if [ -f /etc/config/bugcheck ]
+    then
+    . /etc/config/bugcheck
+fi
+
+if [ $DO_BUGCHECK == 0 ]
+then
+    exit 0
+fi
+
+while true
+  do
+  $CHECKER
+  sleep $SLEEPFOR
+done
diff --git a/package/utils/dtc/Makefile b/package/utils/dtc/Makefile
new file mode 100644
index 0000000..8b5eecc
--- /dev/null
+++ b/package/utils/dtc/Makefile
@@ -0,0 +1,107 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Copyright (C) 2016-2019 Yousong Zhou <yszhou4tech@gmail.com>
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=dtc
+PKG_VERSION:=1.7.1
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_HASH:=9532f10098455711a4da37816fd567dfc8523bb01f59ad6c44887a112e553d9e
+PKG_SOURCE_URL:=@KERNEL/software/utils/dtc
+
+PKG_MAINTAINER:=Yousong Zhou <yszhou4tech@gmail.com>
+PKG_LICENSE:=GPL-2.0-only
+PKG_LICENSE_FILES:=GPL
+PKG_CPE_ID:=cpe:/a:dtc_project:dtc
+
+PKG_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/meson.mk
+
+define Package/dtc
+  SECTION:=utils
+  CATEGORY:=Utilities
+  TITLE:=Device Tree Compiler
+  URL:=https://git.kernel.org/pub/scm/utils/dtc/dtc.git
+endef
+
+define Package/dtc/description
+  Device Tree Compiler for Flat Device Trees Device Tree Compiler, dtc, takes
+  as input a device-tree in a given format and outputs a device-tree in another
+  format for booting kernels on embedded systems.
+endef
+
+define Package/dtc/config
+	config DTC_STATIC_BUILD
+		depends on PACKAGE_dtc
+		bool "Build dtc as static binary"
+		default n
+		help
+			Builds dtc as a static binary.
+			This is usefull in order to export live DTS from a device running
+			various vendor modified OpenWrt versions.
+endef
+
+define Package/dtc/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(CP) $(PKG_INSTALL_DIR)/usr/bin/dtc $(1)/usr/bin
+endef
+
+
+# See Documentation/manual.txt for details about each utility
+define Package/fdt-utils
+  SECTION:=utils
+  CATEGORY:=Utilities
+  TITLE:=Flat Device Tree Utilities
+  URL:=https://git.kernel.org/pub/scm/utils/dtc/dtc.git
+  DEPENDS:=+libfdt
+endef
+
+define Package/fdt-utils/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/convert-dtsv0 $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/fdtdump $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/fdtget $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/fdtput $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/fdtoverlay $(1)/usr/bin
+endef
+
+
+define Package/libfdt
+  SECTION:=libs
+  CATEGORY:=Libraries
+  TITLE:=a utility library for reading and manipulating dtb files
+  URL:=https://git.kernel.org/pub/scm/utils/dtc/dtc.git
+endef
+
+define Package/libfdt/description
+  This is a library containing functions for manipulating Flat Device Trees.
+endef
+
+define Package/libfdt/install
+	$(INSTALL_DIR) $(1)/usr/lib
+	$(CP) $(PKG_INSTALL_DIR)/usr/lib/libfdt*.so* $(1)/usr/lib
+endef
+
+MESON_ARGS += \
+	-Dtests=false \
+	-Dtools=true \
+	-Dyaml=disabled \
+	-Dvalgrind=disabled \
+	-Dpython=disabled \
+	-Dstatic-build=$(if $(CONFIG_DTC_STATIC_BUILD),true,false)
+
+define Build/InstallDev
+	$(INSTALL_DIR) $(1)/usr/lib
+	$(INSTALL_DIR) $(1)/usr/include
+	$(CP) $(PKG_INSTALL_DIR)/usr/include/* $(1)/usr/include
+	$(CP) $(PKG_INSTALL_DIR)/usr/lib/* $(1)/usr/lib
+endef
+
+$(eval $(call BuildPackage,dtc))
+$(eval $(call BuildPackage,fdt-utils))
+$(eval $(call BuildPackage,libfdt))
diff --git a/package/utils/e2fsprogs/Makefile b/package/utils/e2fsprogs/Makefile
new file mode 100644
index 0000000..16b4774
--- /dev/null
+++ b/package/utils/e2fsprogs/Makefile
@@ -0,0 +1,339 @@
+#
+# Copyright (C) 2006-2014 OpenWrt.org
+# Copyright 2010 Vertical Communications
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=e2fsprogs
+PKG_VERSION:=1.47.0
+PKG_RELEASE:=2
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=@KERNEL/linux/kernel/people/tytso/e2fsprogs/v$(PKG_VERSION)/
+PKG_HASH:=144af53f2bbd921cef6f8bea88bb9faddca865da3fbc657cc9b4d2001097d5db
+
+PKG_LICENSE:=GPL-2.0
+PKG_LICENSE_FILES:=NOTICE
+PKG_CPE_ID:=cpe:/a:e2fsprogs_project:e2fsprogs
+
+PKG_BUILD_DEPENDS:=util-linux
+PKG_INSTALL:=1
+
+PKG_BUILD_PARALLEL:=1
+PKG_BUILD_FLAGS:=gc-sections lto
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/host-build.mk
+
+define Package/e2fsprogs
+  SECTION:=utils
+  CATEGORY:=Utilities
+  SUBMENU:=Filesystem
+  TITLE:=Ext2/3/4 filesystem utilities
+  URL:=http://e2fsprogs.sourceforge.net/
+  DEPENDS:=+libuuid +libext2fs +libe2p
+endef
+
+define Package/e2fsprogs/description
+ This package contains essential ext2 filesystem utilities which consists of
+ e2fsck, mke2fs and most of the other core ext2 filesystem utilities.
+endef
+
+define Package/libext2fs
+  SECTION:=libs
+  CATEGORY:=Libraries
+  TITLE:=ext2/3/4 filesystem library
+  URL:=http://e2fsprogs.sourceforge.net/
+  DEPENDS:=+libuuid +libblkid +libss +libcomerr
+  ABI_VERSION:=2
+endef
+
+define Package/libext2fs/description
+ libext2fs is a library which can access ext2, ext3 and ext4 filesystems.
+endef
+
+define Package/libe2p
+  SECTION:=libs
+  CATEGORY:=Libraries
+  TITLE:=ext2fs userspace programs utility library
+  URL:=http://e2fsprogs.sourceforge.net/
+  DEPENDS:=+libuuid
+  ABI_VERSION:=2
+endef
+
+define Package/libe2p/description
+ This package contains libe2p, ext2fs userspace programs utility library
+ bundled with e2fsprogs.
+endef
+
+define Package/libss
+  SECTION:=libs
+  CATEGORY:=Libraries
+  TITLE:=command-line interface parsing library
+  URL:=http://e2fsprogs.sourceforge.net/
+  DEPENDS:=+libcomerr
+  ABI_VERSION:=2
+endef
+
+define Package/libss/description
+  This pacakge contains libss, a command-line interface parsing library
+  bundled with e2fsprogs.
+endef
+
+define Package/libcomerr
+  SECTION:=libs
+  CATEGORY:=Libraries
+  TITLE:=common error description library
+  URL:=http://e2fsprogs.sourceforge.net/
+  DEPENDS:=+libuuid
+  ABI_VERSION:=0
+endef
+
+define Package/libcomerr/description
+  This package contains libcom_err, the common error description library
+  bundled with e2fsprogs.
+endef
+
+define Package/tune2fs
+$(call Package/e2fsprogs)
+  TITLE:=Ext2 Filesystem tune utility
+  DEPENDS:= +e2fsprogs
+endef
+
+define Package/resize2fs
+$(call Package/e2fsprogs)
+  TITLE:=Ext2 Filesystem resize utility
+  DEPENDS:= +e2fsprogs
+endef
+
+define Package/badblocks
+$(call Package/e2fsprogs)
+  TITLE:=Ext2 Filesystem badblocks utility
+  DEPENDS:= +e2fsprogs
+endef
+
+define Package/dumpe2fs
+$(call Package/e2fsprogs)
+  TITLE:=Ext2 Filesystem information dumping utility
+  DEPENDS:= +e2fsprogs
+endef
+
+define Package/e2freefrag
+$(call Package/e2fsprogs)
+  TITLE:=Ext2 Filesystem free space fragmentation information utility
+  DEPENDS:= +e2fsprogs
+endef
+
+define Package/e4crypt
+$(call Package/e2fsprogs)
+  TITLE:=Ext4 Filesystem encryption utility
+  DEPENDS:= +e2fsprogs
+endef
+
+define Package/filefrag
+$(call Package/e2fsprogs)
+  TITLE:=Ext2 Filesystem file fragmentation report utility
+  DEPENDS:= +e2fsprogs
+endef
+
+define Package/debugfs
+$(call Package/e2fsprogs)
+  TITLE:=Ext2 Filesystem debugger
+  DEPENDS:= +e2fsprogs
+endef
+
+define Package/chattr
+$(call Package/e2fsprogs)
+  TITLE:=Ext2 Filesystem chattr utility
+  DEPENDS:= +e2fsprogs
+endef
+
+define Package/lsattr
+$(call Package/e2fsprogs)
+  TITLE:=Ext2 Filesystem lsattr utility
+  DEPENDS:= +e2fsprogs
+endef
+
+TARGET_CFLAGS += $(FPIC)
+
+CONFIGURE_ARGS += \
+	--disable-testio-debug \
+	--enable-elf-shlibs	\
+	--disable-libuuid	\
+	--disable-libblkid	\
+	--disable-uuidd		\
+	--disable-tls		\
+	--disable-nls		\
+	--disable-rpath		\
+	--disable-fuse2fs
+
+ifneq ($(CONFIG_USE_MUSL),)
+  CONFIGURE_VARS += ac_cv_func_lseek64=yes
+endif
+
+define Build/Prepare
+	$(call Build/Prepare/Default)
+	$(CP) $(SCRIPT_DIR)/config.{guess,sub} $(PKG_BUILD_DIR)/config/
+endef
+
+define Build/Compile
+	+$(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR)/util \
+		BUILDCC="$(HOSTCC)" \
+		CFLAGS="" \
+		CPPFLAGS="" \
+		LDFLAGS="" \
+		V=$(if $(findstring c,$(OPENWRT_VERBOSE)),1,) \
+		subst
+	+$(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR) \
+		BUILDCC="$(HOSTCC)" \
+		DESTDIR="$(PKG_INSTALL_DIR)" \
+		ELF_OTHER_LIBS="$(TARGET_LDFLAGS) -luuid" \
+		SYSLIBS="$(TARGET_LDFLAGS) -ldl -L$(PKG_BUILD_DIR)/lib/ -l:libcom_err.so.0.0" \
+		V=$(if $(findstring c,$(OPENWRT_VERBOSE)),1,) \
+		all
+endef
+
+define Build/InstallDev
+	$(INSTALL_DIR) $(1)/usr/lib/pkgconfig
+
+	$(CP) $(PKG_BUILD_DIR)/lib/ext2fs/ext2fs.pc $(1)/usr/lib/pkgconfig
+	$(CP) $(PKG_BUILD_DIR)/lib/et/com_err.pc $(1)/usr/lib/pkgconfig
+	$(CP) $(PKG_BUILD_DIR)/lib/e2p/e2p.pc $(1)/usr/lib/pkgconfig
+	$(CP) $(PKG_BUILD_DIR)/lib/ss/ss.pc $(1)/usr/lib/pkgconfig
+
+	$(INSTALL_DIR) $(1)/usr/lib
+	$(CP) $(PKG_BUILD_DIR)/lib/libext2fs.{so,a}* $(1)/usr/lib
+	$(CP) $(PKG_BUILD_DIR)/lib/libcom_err.{so,a}* $(1)/usr/lib
+	$(CP) $(PKG_BUILD_DIR)/lib/libss.{so,a}* $(1)/usr/lib
+	$(CP) $(PKG_BUILD_DIR)/lib/libe2p.{so,a}* $(1)/usr/lib
+
+	$(INSTALL_DIR) $(1)/usr/include/ext2fs
+	$(CP) $(PKG_BUILD_DIR)/lib/ext2fs/*.h $(1)/usr/include/ext2fs
+	$(INSTALL_DIR) $(1)/usr/include/et
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/lib/et/*.h $(1)/usr/include/et
+	# Apparently there is some confusion
+	echo "#include <et/com_err.h>" > $(1)/usr/include/com_err.h
+	$(INSTALL_DIR) $(1)/usr/include/ss
+	$(CP) \
+		$(PKG_BUILD_DIR)/lib/ss/ss.h \
+		$(PKG_BUILD_DIR)/lib/ss/ss_err.h \
+		$(1)/usr/include/ss/
+	$(INSTALL_DIR) $(1)/usr/include/e2p
+	$(CP) $(PKG_BUILD_DIR)/lib/e2p/e2p.h $(1)/usr/include/e2p
+endef
+
+define Package/e2fsprogs/conffiles
+/etc/e2fsck.conf
+endef
+
+define Package/e2fsprogs/install
+	$(INSTALL_DIR) $(1)/usr/sbin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/e2fsck $(1)/usr/sbin/
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/mke2fs $(1)/usr/sbin/
+	$(LN) mke2fs $(1)/usr/sbin/mkfs.ext2
+	$(LN) mke2fs $(1)/usr/sbin/mkfs.ext3
+	$(LN) mke2fs $(1)/usr/sbin/mkfs.ext4
+	$(LN) e2fsck $(1)/usr/sbin/fsck.ext2
+	$(LN) e2fsck $(1)/usr/sbin/fsck.ext3
+	$(LN) e2fsck $(1)/usr/sbin/fsck.ext4
+	$(INSTALL_DIR) $(1)/usr/lib
+	$(INSTALL_DIR) $(1)/etc/init.d
+	$(INSTALL_DIR) $(1)/lib/functions/fsck
+	$(INSTALL_DATA) ./files/e2fsck.sh $(1)/lib/functions/fsck/
+	$(INSTALL_DATA) ./files/e2fsck.conf $(1)/etc/e2fsck.conf
+endef
+
+define Package/libe2p/install
+	$(INSTALL_DIR) $(1)/usr/lib
+	$(CP) $(PKG_INSTALL_DIR)/usr/lib/libe2p.so.* $(1)/usr/lib/
+endef
+
+define Package/libcomerr/install
+	$(INSTALL_DIR) $(1)/usr/lib
+	$(CP) $(PKG_INSTALL_DIR)/usr/lib/libcom_err.so.* $(1)/usr/lib/
+endef
+
+define Package/libss/install
+	$(INSTALL_DIR) $(1)/usr/lib
+	$(CP) $(PKG_INSTALL_DIR)/usr/lib/libss.so.* $(1)/usr/lib/
+endef
+
+define Package/libext2fs/install
+	$(INSTALL_DIR) $(1)/usr/lib
+	$(CP) $(PKG_INSTALL_DIR)/usr/lib/libext2fs.so.* $(1)/usr/lib/
+endef
+
+define Package/libext2fs/install_lib
+	$(INSTALL_DIR) $(1)/usr/lib
+	$(CP) $(PKG_BUILD_DIR)/lib/ext2fs/libext2fs.a $(1)/usr/lib/libext2fs_pic.a
+endef
+
+define Package/tune2fs/install
+	$(INSTALL_DIR) $(1)/usr/sbin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/tune2fs $(1)/usr/sbin/
+endef
+
+define Package/resize2fs/install
+	$(INSTALL_DIR) $(1)/usr/sbin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/resize2fs $(1)/usr/sbin/
+endef
+
+define Package/badblocks/install
+	$(INSTALL_DIR) $(1)/usr/sbin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/badblocks $(1)/usr/sbin/
+endef
+
+define Package/dumpe2fs/install
+	$(INSTALL_DIR) $(1)/usr/sbin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/dumpe2fs $(1)/usr/sbin/
+endef
+
+define Package/e2freefrag/install
+	$(INSTALL_DIR) $(1)/usr/sbin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/e2freefrag $(1)/usr/sbin/
+endef
+
+define Package/e4crypt/install
+	$(INSTALL_DIR) $(1)/usr/sbin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/e4crypt $(1)/usr/sbin/
+endef
+
+define Package/filefrag/install
+	$(INSTALL_DIR) $(1)/usr/sbin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/filefrag $(1)/usr/sbin/
+endef
+
+define Package/debugfs/install
+	$(INSTALL_DIR) $(1)/usr/sbin
+	$(INSTALL_DIR) $(1)/usr/lib
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/debugfs $(1)/usr/sbin/
+endef
+
+define Package/chattr/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/chattr $(1)/usr/bin/
+endef
+
+define Package/lsattr/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/lsattr $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,libcomerr))
+$(eval $(call BuildPackage,libss))
+$(eval $(call BuildPackage,libext2fs))
+$(eval $(call BuildPackage,libe2p))
+$(eval $(call BuildPackage,e2fsprogs))
+$(eval $(call BuildPackage,tune2fs))
+$(eval $(call BuildPackage,resize2fs))
+$(eval $(call BuildPackage,badblocks))
+$(eval $(call BuildPackage,dumpe2fs))
+$(eval $(call BuildPackage,e2freefrag))
+$(eval $(call BuildPackage,e4crypt))
+$(eval $(call BuildPackage,filefrag))
+$(eval $(call BuildPackage,debugfs))
+$(eval $(call BuildPackage,chattr))
+$(eval $(call BuildPackage,lsattr))
diff --git a/package/utils/e2fsprogs/files/e2fsck.conf b/package/utils/e2fsprogs/files/e2fsck.conf
new file mode 100644
index 0000000..9c96b49
--- /dev/null
+++ b/package/utils/e2fsprogs/files/e2fsck.conf
@@ -0,0 +1,3 @@
+[options]
+broken_system_clock = true
+
diff --git a/package/utils/e2fsprogs/files/e2fsck.sh b/package/utils/e2fsprogs/files/e2fsck.sh
new file mode 100644
index 0000000..22031ed
--- /dev/null
+++ b/package/utils/e2fsprogs/files/e2fsck.sh
@@ -0,0 +1,38 @@
+#!/bin/sh
+# Copyright 2010 Vertical Communications
+# Copyright 2012 OpenWrt.org
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+fsck_e2fsck() {
+	set -o pipefail
+	e2fsck -p "$device" 2>&1 | logger -t "fstab: e2fsck ($device)"
+	local status="$?"
+	set +o pipefail
+	case "$status" in
+		0|1) ;; #success
+		2) reboot;;
+		4) echo "e2fsck ($device): Warning! Uncorrected errors."| logger -t fstab
+			return 1
+			;;
+		*) echo "e2fsck ($device): Error $status. Check not complete."| logger -t fstab;;
+	esac
+	return 0
+}
+
+fsck_ext2() {
+	fsck_e2fsck "$@"
+}
+
+fsck_ext3() {
+	fsck_e2fsck "$@"
+}
+
+fsck_ext4() {
+	fsck_e2fsck "$@"
+}
+
+append libmount_known_fsck "ext2"
+append libmount_known_fsck "ext3"
+append libmount_known_fsck "ext4"
diff --git a/package/utils/e2fsprogs/patches/000-relocatable.patch b/package/utils/e2fsprogs/patches/000-relocatable.patch
new file mode 100644
index 0000000..0bf226f
--- /dev/null
+++ b/package/utils/e2fsprogs/patches/000-relocatable.patch
@@ -0,0 +1,40 @@
+--- a/lib/et/compile_et.sh.in
++++ b/lib/et/compile_et.sh.in
+@@ -2,8 +2,14 @@
+ #
+ #
+ 
+-AWK=@AWK@
+-DIR=@datadir@/et
++if test "x$STAGING_DIR" = x ; then
++	AWK=@AWK@
++	DIR=@datadir@/et
++else
++	AWK=awk
++	DIR="$STAGING_DIR/../hostpkg/share/et"
++fi
++
+ 
+ if test "$1" = "--build-tree" ; then
+     shift;
+--- a/lib/ss/mk_cmds.sh.in
++++ b/lib/ss/mk_cmds.sh.in
+@@ -2,10 +2,16 @@
+ #
+ #
+ 
+-DIR=@datadir@/ss
+-AWK=@AWK@
+ SED=sed
+ 
++if test "x$STAGING_DIR" = x ; then
++	DIR=@datadir@/ss
++	AWK=@AWK@
++else
++	DIR="$STAGING_DIR/../hostpkg/share/ss"
++	AWK=awk
++fi
++
+ for as_var in \
+   LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+   LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
diff --git a/package/utils/e2fsprogs/patches/001-com_err_version.patch b/package/utils/e2fsprogs/patches/001-com_err_version.patch
new file mode 100644
index 0000000..c808963
--- /dev/null
+++ b/package/utils/e2fsprogs/patches/001-com_err_version.patch
@@ -0,0 +1,13 @@
+--- a/lib/et/Makefile.in
++++ b/lib/et/Makefile.in
+@@ -26,8 +26,8 @@ SHARE_FILES= et_c.awk et_h.awk
+ LIBRARY= libcom_err
+ LIBDIR= et
+ 
+-ELF_VERSION = 2.1
+-ELF_SO_VERSION = 2
++ELF_VERSION = 0.0
++ELF_SO_VERSION = 0
+ ELF_IMAGE = libcom_err
+ ELF_MYDIR = et
+ ELF_INSTALL_DIR = $(root_libdir)
diff --git a/package/utils/e2fsprogs/patches/002-fix-subst-host-build.patch b/package/utils/e2fsprogs/patches/002-fix-subst-host-build.patch
new file mode 100644
index 0000000..5c28a59
--- /dev/null
+++ b/package/utils/e2fsprogs/patches/002-fix-subst-host-build.patch
@@ -0,0 +1,10 @@
+--- a/util/subst.c
++++ b/util/subst.c
+@@ -10,6 +10,7 @@
+ #else
+ #define HAVE_SYS_STAT_H
+ #define HAVE_SYS_TIME_H
++#define HAVE_SYS_STAT_H
+ #endif
+ #include <stdio.h>
+ #include <errno.h>
diff --git a/package/utils/f2fs-tools/Makefile b/package/utils/f2fs-tools/Makefile
new file mode 100644
index 0000000..d11e89d
--- /dev/null
+++ b/package/utils/f2fs-tools/Makefile
@@ -0,0 +1,160 @@
+#
+# Copyright (C) 2014 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=f2fs-tools
+PKG_VERSION:=1.16.0
+PKG_RELEASE:=3
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs-tools.git/snapshot/
+PKG_HASH:=208c7a07e95383fbd7b466b5681590789dcb41f41bf197369c41a95383b57c5e
+
+PKG_MAINTAINER:=Felix Fietkau <nbd@nbd.name>
+PKG_LICENSE:=GPL-2.0-only
+PKG_LICENSE_FILES:=COPYING
+PKG_CPE_ID:=cpe:/a:f2fs-tools_project:f2fs-tools
+
+PKG_FIXUP:=autoreconf
+PKG_BUILD_PARALLEL:=1
+PKG_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/f2fs-tools/Default
+  SECTION:=utils
+  CATEGORY:=Utilities
+  SUBMENU:=Filesystem
+  DEPENDS:=+libf2fs
+  URL:=http://git.kernel.org/cgit/linux/kernel/git/jaegeuk/f2fs-tools.git
+  VARIANT:=default
+endef
+
+define Package/f2fs-tools/SELinux
+  SECTION:=utils
+  CATEGORY:=Utilities
+  SUBMENU:=Filesystem
+  DEPENDS:=+libf2fs-selinux +libselinux
+  URL:=http://git.kernel.org/cgit/linux/kernel/git/jaegeuk/f2fs-tools.git
+  VARIANT:=selinux
+endef
+
+define Package/mkf2fs
+  $(Package/f2fs-tools/Default)
+  TITLE:=Utility for creating a Flash-Friendly File System (F2FS)
+  CONFLICTS:=mkf2fs-selinux
+endef
+
+define Package/mkf2fs-selinux
+  $(Package/f2fs-tools/SELinux)
+  TITLE:=Utility for creating a Flash-Friendly File System (F2FS) with SELinux support
+endef
+
+define Package/f2fsck
+  $(Package/f2fs-tools/Default)
+  TITLE:=Utility for checking/repairing a Flash-Friendly File System (F2FS)
+  CONFLICTS:=f2fsck-selinux
+endef
+
+define Package/f2fsck-selinux
+  $(Package/f2fs-tools/SELinux)
+  TITLE:=Utility for checking/repairing a Flash-Friendly File System (F2FS) with SELinux support
+endef
+
+define Package/f2fs-tools
+  $(Package/f2fs-tools/Default)
+  TITLE:=Tools for Flash-Friendly File System (F2FS)
+  DEPENDS += +mkf2fs +f2fsck
+  CONFLICTS:=f2fs-tools-selinux
+endef
+
+define Package/f2fs-tools-selinux
+  $(Package/f2fs-tools/SELinux)
+  TITLE:=Tools for Flash-Friendly File System (F2FS) with SELinux support
+  DEPENDS += +mkf2fs-selinux +f2fsck-selinux
+endef
+
+define Package/libf2fs
+  SECTION:=libs
+  CATEGORY:=Libraries
+  TITLE:=Library for Flash-Friendly File System (F2FS) tools
+  DEPENDS:=+libuuid
+  ABI_VERSION:=6
+  CONFLICTS:=libf2fs-selinux
+  VARIANT:=default
+endef
+
+define Package/libf2fs-selinux
+  SECTION:=libs
+  CATEGORY:=Libraries
+  TITLE:=Library for Flash-Friendly File System (F2FS) tools with SELinux support
+  DEPENDS:=+libuuid +libselinux
+  ABI_VERSION:=6
+  VARIANT:=selinux
+endef
+
+CONFIGURE_ARGS += \
+	--disable-static \
+	--without-blkid \
+	--without-lzo2 \
+	--without-lz4
+
+ifneq ($(BUILD_VARIANT),selinux)
+  CONFIGURE_ARGS += --without-selinux
+endif
+
+CONFIGURE_VARS += \
+	ac_cv_file__git=no
+
+ifneq ($(CONFIG_USE_MUSL),)
+  CONFIGURE_VARS += ac_cv_func_lseek64=yes
+endif
+
+define Package/libf2fs/install
+	$(INSTALL_DIR) $(1)/usr/lib
+	$(CP) \
+		$(PKG_INSTALL_DIR)/usr/lib/libf2fs.so.* $(1)/usr/lib/
+endef
+
+Package/libf2fs-selinux/install = $(Package/libf2fs/install)
+
+define Package/mkf2fs/install
+	$(INSTALL_DIR) $(1)/usr/sbin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/mkfs.f2fs $(1)/usr/sbin
+endef
+
+Package/mkf2fs-selinux/install = $(Package/mkf2fs/install)
+
+define Package/f2fsck/install
+	$(INSTALL_DIR) $(1)/usr/sbin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/fsck.f2fs $(1)/usr/sbin
+	$(LN) ../sbin/fsck.f2fs $(1)/usr/sbin/defrag.f2fs
+	$(LN) ../sbin/fsck.f2fs $(1)/usr/sbin/dump.f2fs
+	$(LN) ../sbin/fsck.f2fs $(1)/usr/sbin/sload.f2fs
+	$(LN) ../sbin/fsck.f2fs $(1)/usr/sbin/resize.f2fs
+	$(LN) ../sbin/fsck.f2fs $(1)/usr/sbin/f2fslabel
+endef
+
+Package/f2fsck-selinux/install = $(Package/f2fsck/install)
+
+define Package/f2fs-tools/install
+	$(INSTALL_DIR) $(1)/usr/sbin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/fibmap.f2fs $(1)/usr/sbin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/parse.f2fs $(1)/usr/sbin
+endef
+
+Package/f2fs-tools-selinux/install = $(Package/f2fs-tools/install)
+
+$(eval $(call BuildPackage,libf2fs))
+$(eval $(call BuildPackage,libf2fs-selinux))
+$(eval $(call BuildPackage,mkf2fs))
+$(eval $(call BuildPackage,mkf2fs-selinux))
+$(eval $(call BuildPackage,f2fsck))
+$(eval $(call BuildPackage,f2fsck-selinux))
+$(eval $(call BuildPackage,f2fs-tools))
+$(eval $(call BuildPackage,f2fs-tools-selinux))
diff --git a/package/utils/fbtest/Makefile b/package/utils/fbtest/Makefile
new file mode 100644
index 0000000..464b34f
--- /dev/null
+++ b/package/utils/fbtest/Makefile
@@ -0,0 +1,39 @@
+#
+# Copyright (C) 2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=fbtest
+PKG_RELEASE:=1
+
+PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/fbtest
+  SECTION:=utils
+  CATEGORY:=Utilities
+  TITLE:=Frame buffer device testing tool
+  DEPENDS:=@DISPLAY_SUPPORT
+endef
+
+define Build/Configure
+endef
+
+define Build/Compile
+	$(MAKE) -C $(PKG_BUILD_DIR) \
+		CC="$(TARGET_CC)" \
+		CFLAGS="$(TARGET_CFLAGS) -Wall" \
+		LDFLAGS="$(TARGET_LDFLAGS)"
+endef
+
+define Package/fbtest/install
+	$(INSTALL_DIR) $(1)/usr/sbin
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/fbtest $(1)/usr/sbin/
+endef
+
+$(eval $(call BuildPackage,fbtest))
diff --git a/package/utils/fbtest/src/Makefile b/package/utils/fbtest/src/Makefile
new file mode 100644
index 0000000..f7c9f86
--- /dev/null
+++ b/package/utils/fbtest/src/Makefile
@@ -0,0 +1,14 @@
+CC = gcc
+CFLAGS = -Wall
+OBJS = fbtest.o
+
+all: fbtest
+
+%.o: %.c
+	$(CC) $(CFLAGS) -c -o $@ $<
+
+fbtest: $(OBJS)
+	$(CC) -o $@ $(OBJS)
+
+clean:
+	rm -f fbtest *.o
diff --git a/package/utils/fbtest/src/fbtest.c b/package/utils/fbtest/src/fbtest.c
new file mode 100644
index 0000000..021b803
--- /dev/null
+++ b/package/utils/fbtest/src/fbtest.c
@@ -0,0 +1,446 @@
+/******************************************************************************
+ *	fbtest - fbtest.c
+ *	test program for the tuxbox-framebuffer device
+ *	tests all GTX/eNX supported modes
+ *                                                                            
+ *	(c) 2003 Carsten Juttner (carjay@gmx.net)
+ *
+ * 	This program is free software; you can redistribute it and/or modify
+ * 	it under the terms of the GNU General Public License as published by
+ * 	The Free Software Foundation; either version 2 of the License, or
+ * 	(at your option) any later version.
+ *
+ * 	This program is distributed in the hope that it will be useful,
+ * 	but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * 	GNU General Public License for more details.
+ *
+ * 	You should have received a copy of the GNU General Public License
+ * 	along with this program; if not, write to the Free Software
+ * 	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *  									      
+ ******************************************************************************
+ * $Id: fbtest.c,v 1.5 2005/01/14 23:14:41 carjay Exp $
+ ******************************************************************************/
+
+// TODO: - should restore the colour map and mode to what it was before
+//	 - is colour map handled correctly?
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+
+#include <linux/fb.h>
+
+#define FBDEV "/dev/fb0"
+
+struct vidsize{
+	int width;
+	int height;
+};
+static
+const struct vidsize vidsizetable[]={	// all supported sizes
+	{720,576},{720,480},{720,288},{720,240},
+	{640,576},{640,480},{640,288},{640,240},
+	{360,576},{360,480},{360,288},{360,240},
+	{320,576},{320,480},{320,288},{320,240}
+};
+#define VIDSIZENUM (sizeof(vidsizetable)/sizeof(struct vidsize))
+
+enum pixenum{	// keep in sync with pixname !
+	CLUT4=0,
+	CLUT8,
+	RGB565,
+	ARGB1555,
+	ARGB
+};
+const char *pixname[] = {
+	"CLUT4",
+	"CLUT8",
+	"RGB565",
+	"ARGB1555",
+	"ARGB"
+};
+
+struct pixelformat{
+	char *name;
+	struct fb_bitfield red;
+	struct fb_bitfield green;
+	struct fb_bitfield blue;
+	struct fb_bitfield transp;
+	char bpp;
+	char pixenum;
+};
+
+static		// so far these are all modes supported by the eNX (only partially by GTX)
+const struct pixelformat pixelformattable[] = {
+	{ .name = "CLUT4 ARGB8888", 	// CLUT4 (ARGB8888)
+		.bpp = 4, .pixenum = CLUT4,
+		.red = 	 { .offset = 0, .length=8, .msb_right =0 },
+		.green = { .offset = 0, .length=8, .msb_right =0 },
+		.blue =  { .offset = 0, .length=8, .msb_right =0 },
+		.transp=  { .offset = 0, .length=8, .msb_right =0 }
+	},
+	{ .name = "CLUT4 ARGB1555", 	// CLUT4 (ARGB1555)
+		.bpp = 4, .pixenum = CLUT4,
+		.red = 	 { .offset = 0, .length=5, .msb_right =0 },
+		.green = { .offset = 0, .length=5, .msb_right =0 },
+		.blue =  { .offset = 0, .length=5, .msb_right =0 },
+		.transp=  { .offset = 0, .length=1, .msb_right =0 }
+	},
+	{ .name = "CLUT8 ARGB8888",	// CLUT8 (ARGB8888)
+		.bpp = 8, .pixenum = CLUT8,
+		.red = 	 { .offset = 0, .length=8, .msb_right =0 },
+		.green = { .offset = 0, .length=8, .msb_right =0 },
+		.blue =  { .offset = 0, .length=8, .msb_right =0 },
+		.transp=  { .offset = 0, .length=8, .msb_right =0 }
+	},
+	{ .name = "CLUT8 ARGB1555",	// CLUT8 (ARGB1555)
+		.bpp = 8, .pixenum = CLUT8,
+		.red = 	 { .offset = 0, .length=5, .msb_right =0 },
+		.green = { .offset = 0, .length=5, .msb_right =0 },
+		.blue =  { .offset = 0, .length=5, .msb_right =0 },
+		.transp=  { .offset = 0, .length=1, .msb_right =0 }
+	},
+	{ .name = "ARGB1555", 	// ARGB1555
+		.bpp = 16, .pixenum = ARGB1555,
+		.red = 	 { .offset = 10, .length=5, .msb_right =0 },
+		.green = { .offset = 5,  .length=5, .msb_right =0 },
+		.blue =  { .offset = 0,  .length=5, .msb_right =0 },
+		.transp=  { .offset = 15, .length=1, .msb_right =0 }
+	},
+	{ .name = "RGB565", 		// RGB565
+		.bpp = 16, .pixenum = RGB565,
+		.red = 	 { .offset = 11, .length=5, .msb_right =0 },
+		.green = { .offset = 5,  .length=6, .msb_right =0 },
+		.blue =  { .offset = 0,  .length=5, .msb_right =0 },
+		.transp=  { .offset = 0,  .length=0, .msb_right =0 }
+	},
+	{ .name = "ARGB",	// 32 f*cking bits, the real McCoy :)
+		.bpp = 32, .pixenum = ARGB,
+		.red = 	 { .offset = 16, .length=8, .msb_right =0 },
+		.green = { .offset = 8,  .length=8, .msb_right =0 },
+		.blue =  { .offset = 0,  .length=8, .msb_right =0 },
+		.transp=  { .offset = 24, .length=8, .msb_right =0 }
+	}
+};
+#define PIXELFORMATNUM (sizeof(pixelformattable)/sizeof(struct pixelformat))
+
+struct colour {
+	__u16 r;
+	__u16 g;
+	__u16 b;
+	__u16 a;
+};
+static
+struct colour colourtable[] = {
+	{.r =0xffff, .g = 0xffff, .b=0xffff, .a=0xffff},	// fully transparent white
+	{.r =0xffff, .g = 0x0000, .b=0x0000, .a=0x0000},	// red
+	{.r =0x0000, .g = 0xffff, .b=0x0000, .a=0x0000},	// green
+	{.r =0x0000, .g = 0x0000, .b=0xffff, .a=0x0000},	// blue
+	{.r =0x0000, .g = 0x0000, .b=0x0000, .a=0x0000}		// black
+};
+#define COLOURNUM (sizeof(colourtable)/sizeof(struct colour))
+
+struct rect{
+	int x;
+	int y;
+	int width;
+	int height;
+	const struct colour *col;
+};
+struct pixel{		// up to 32 bits of pixel information
+	char byte[4];
+};
+
+void col2pixel (struct pixel *pix, const struct pixelformat *pixf, const struct colour *col){
+	switch (pixf->pixenum){
+		case RGB565:
+			pix->byte[0]=(col->r&0xf8)|(col->g&0xfc)>>5;
+			pix->byte[1]=(col->g&0xfc)<<3|(col->b&0xf8)>>3;
+			break;
+		case ARGB1555:
+			pix->byte[0]=(col->a&0x80)|(col->r&0xf8)>>1|(col->g&0xf8)>>6;
+			pix->byte[1]=(col->g&0xf8)<<2|(col->b&0xf8)>>3;
+			break;
+		case ARGB:
+			pix->byte[0]=col->a;
+			pix->byte[1]=col->r;
+			pix->byte[2]=col->g;
+			pix->byte[3]=col->b;
+			break;
+		default:
+			printf ("unknown pixelformat\n");
+			exit(1);
+	}
+}
+
+int setmode(int fbd, const struct pixelformat *pixf,const struct vidsize *vids){
+	struct fb_var_screeninfo var;
+	int stat;
+	stat = ioctl (fbd, FBIOGET_VSCREENINFO,&var);
+	if (stat<0) return -2;
+	
+	var.xres= vids->width;
+	var.xres_virtual = vids->width;
+	var.yres= vids->height;
+	var.yres_virtual = vids->height;
+	
+	var.bits_per_pixel = pixf->bpp;
+	var.red = pixf->red;
+	var.green = pixf->green;
+	var.blue = pixf->blue;
+	var.transp = pixf->transp;
+
+	stat = ioctl (fbd, FBIOPUT_VSCREENINFO,&var);
+	if (stat<0) return -1;
+	return 0;
+}
+
+// unefficient implementation, do NOT use it for your next ego shooter, please :)
+// for 4-Bit only rectangles with even width are supported
+// CLUT-modes use value of red component as index
+void drawrect(void *videoram, struct rect *r, const struct pixelformat *pixf, const struct vidsize *vids){
+	int x,y,corwidth, bpp = 0, tocopy = 1;
+	struct pixel pix;
+	unsigned char *pmem = videoram;
+	corwidth = r->width;	// actually only "corrected" for 4 Bit
+
+	if (pixf->pixenum!=CLUT4&&pixf->pixenum!=CLUT8){
+		switch (pixf->pixenum){
+			case ARGB1555:
+			case RGB565:
+				bpp = 16;
+				tocopy = 2;
+				break;
+			case ARGB:
+				bpp = 32;
+				tocopy = 4;
+				break;
+			default:
+				printf ("drawrect: unknown pixelformat(%d) bpp:%d\n",pixf->pixenum,pixf->bpp);
+				exit(1);
+		}
+		col2pixel(&pix,pixf,r->col);
+	} else {
+		switch (pixf->pixenum){	// CLUT = Colour LookUp Table (palette)
+			case CLUT4:	// take red value as index in this case
+				pix.byte[0]=(r->col->r)<<4|(r->col->r&0xf);	// slightly cryptic... "rect->colour->red"
+				corwidth>>=1;	// we copy bytes
+				bpp=4;
+				tocopy=1;
+				break;
+			case CLUT8:
+				pix.byte[0]=(r->col->r&0xff);
+				bpp=8;
+				tocopy=1;
+				break;
+		}
+	}
+	pmem=videoram+((((r->y*vids->width)+r->x)*bpp)>>3);
+	for (y=0;y<r->height;y++){
+		int offset = 0;
+		for (x=0;x<corwidth;x++){
+			memcpy (pmem+offset,pix.byte,tocopy);
+			offset+=tocopy;
+		}
+		pmem +=((vids->width*bpp)>>3);	// skip one whole line, actually should be taken from "fix-info"
+	}
+}
+			
+// create quick little test image, 4 colours from table
+void draw4field(void *videoram, const struct pixelformat *pixf, const struct vidsize *vids){
+	struct rect r;
+	struct colour c;
+	int height, width;
+	c.r = 1;	// only used for the indexed modes, r is taken as index
+	height = vids->height;
+	width = vids->width;
+
+	r.height = height>>1;
+	r.width = width>>1;
+	r.x = 0;	r.y = 0;
+	if (pixf->pixenum==CLUT4||pixf->pixenum==CLUT8) r.col = &c;
+	else r.col = &colourtable[1];
+	drawrect (videoram, &r, pixf, vids);
+
+	r.x = width/2;	r.y = 0;
+	if (pixf->pixenum==CLUT4||pixf->pixenum==CLUT8) c.r = 2;
+	else r.col = &colourtable[2];
+	drawrect (videoram, &r, pixf, vids);
+
+	r.x = 0;	r.y = height/2;
+	if (pixf->pixenum==CLUT4||pixf->pixenum==CLUT8) c.r = 3;
+	else r.col = &colourtable[3];
+	drawrect (videoram, &r, pixf, vids);
+
+	r.x = width/2;	r.y = height/2;
+	if (pixf->pixenum==CLUT4||pixf->pixenum==CLUT8) c.r = 0;
+	else r.col = &colourtable[0];
+	drawrect (videoram, &r, pixf, vids);
+}
+
+void usage(char *name){
+ 	printf ("Usage: %s [options]\n"
+		"Options: -f<pixelformat>\n"
+		"            where format is one of:\n"
+		"              CLUT4,CLUT8,ARGB1555,RGB565,ARGB\n"
+		"         -s<width>x<heigth>\n"
+		"            where width is either 720,640,360,320\n"
+		"                  and height is either 288,240,480,576\n"
+		"         -n\n"
+		"            disables clearing the framebuffer after drawing\n"
+		"            the testimage. This can be useful to keep the last\n"
+		"            drawn image onscreen.\n"
+		"\nExample: %s -fRGB322\n",name,name);
+	exit(0);
+}
+
+int main (int argc,char **argv){
+	struct fb_fix_screeninfo fix;
+	struct fb_var_screeninfo var;
+	struct fb_cmap cmap;
+	struct rect r;
+	int fbd;
+	unsigned char *pfb;
+	int stat;
+	int optchar,fmode=-1,smode=-1,clear=1;
+	int i_cmap,i_size,i_pix;
+	extern char *optarg;
+	
+	if (argc!=0&&argc>4) usage(argv[0]);
+	while ( (optchar = getopt (argc,argv,"f:s:n"))!= -1){
+		int i,height,width;
+		switch (optchar){
+			case 'f':
+				for (i=0;i<(sizeof(pixname)/sizeof(char*));i++){
+					if (!strncmp (optarg,pixname[i],strlen(pixname[i]))){
+						fmode=i;
+						printf ("displaying only %s-modes\n",pixname[i]);
+						break;
+					}
+				}
+				if (fmode==-1){
+					printf ("unknown pixelformat\n");
+					exit(0);
+				}
+				break;
+			case 's':
+				if (sscanf (optarg,"%dx%d",&width,&height)!=2){
+					printf ("parsing size failed\n");
+					exit(0);
+				} else {
+					printf ("requested size %dx%d\n",width,height);
+					for (i=0;i<VIDSIZENUM;i++){
+						if (vidsizetable[i].width == width &&
+							vidsizetable[i].height == height){
+							smode = i;
+							break;
+						}
+					}
+					if (smode==-1){
+						printf ("this size is not supported\n");
+						exit(0);
+					}
+				}
+				break;
+			case 'n':
+				clear = 0;
+				printf ("clearing framebuffer after drawing is disabled\n");
+				break;
+			case '?':
+				usage (argv[0]);
+		}
+	}
+	
+	fbd = open (FBDEV, O_RDWR);
+	if (fbd<0){
+		perror ("Error opening framebuffer device");
+		return 1;
+	}
+	stat = ioctl (fbd, FBIOGET_FSCREENINFO,&fix);
+	if (stat<0){
+		perror ("Error getting fix screeninfo");
+		return 1;
+	}
+	stat = ioctl (fbd, FBIOGET_VSCREENINFO,&var);
+	if (stat<0){
+		perror ("Error getting var screeninfo");
+		return 1;
+	}
+	stat = ioctl (fbd, FBIOPUT_VSCREENINFO,&var);
+	if (stat<0){
+		perror ("Error setting mode");
+		return 1;
+	}
+	pfb = mmap (0, fix.smem_len, PROT_READ|PROT_WRITE, MAP_SHARED, fbd, 0);
+	if (pfb == MAP_FAILED){
+		perror ("Error mmap'ing framebuffer device");
+		return 1;
+	}
+
+	// iterate over all modes
+	for (i_pix=0;i_pix<PIXELFORMATNUM;i_pix++){
+		if (fmode!=-1 && pixelformattable[i_pix].pixenum != fmode) continue;
+		printf ("testing: %s",pixelformattable[i_pix].name);
+		printf (" for sizes: \n");
+		for (i_size=0;i_size<VIDSIZENUM;i_size++){
+			if (smode!=-1 && i_size!=smode) continue;
+			printf ("%dx%d ",vidsizetable[i_size].width,vidsizetable[i_size].height);
+			fflush(stdout);
+			if ((i_size%4)==3) printf ("\n");
+			
+			// try to set mode
+			stat = setmode(fbd,&pixelformattable[i_pix],&vidsizetable[i_size]);
+			if (stat==-2) perror ("fbtest: could not get fb_var-screeninfo from fb-device");
+			else if (stat==-1){
+				printf ("\nCould not set mode %s (%dx%d), possible reasons:\n"
+					"- you have a GTX (soz m8)\n"
+					"- your configuration does not have enough graphics RAM\n"
+					"- you found a bug\n"
+					"choose your poison accordingly...\n",
+					pixelformattable[i_pix].name,vidsizetable[i_size].width,vidsizetable[i_size].height);
+					continue;
+			}
+			// fill cmap;
+			cmap.len = 1;
+			if ((pixelformattable[i_pix].bpp==4)||
+				((pixelformattable[i_pix].bpp==8)&&(pixelformattable[i_pix].red.length!=3))){
+				for (i_cmap=0;i_cmap<COLOURNUM;i_cmap++){
+					cmap.start=i_cmap;
+					cmap.red=&colourtable[i_cmap].r;
+					cmap.green=&colourtable[i_cmap].g;
+					cmap.blue=&colourtable[i_cmap].b;
+					cmap.transp=&colourtable[i_cmap].a;
+					stat = ioctl (fbd, FBIOPUTCMAP, &cmap);
+					if (stat<0) printf ("setting colourmap failed\n");
+				}
+			}
+			// create the test image
+			draw4field(pfb,&pixelformattable[i_pix],&vidsizetable[i_size]);
+			usleep (500000);
+			// clear screen
+			if (clear){
+				r.x=r.y=0;r.width = vidsizetable[i_size].width; r.height = vidsizetable[i_size].height;
+				r.col = &colourtable[4];
+				drawrect(pfb,&r,&pixelformattable[i_pix],&vidsizetable[i_size]);
+			}
+		}
+		printf ("\n");
+	}
+
+	stat = munmap (pfb,fix.smem_len);
+	if (stat<0){
+		perror ("Error munmap'ing framebuffer device");
+		return 1;
+	}
+	close (fbd);
+	return 0;
+}
diff --git a/package/utils/firmware-utils/Makefile b/package/utils/firmware-utils/Makefile
new file mode 100644
index 0000000..65b7048
--- /dev/null
+++ b/package/utils/firmware-utils/Makefile
@@ -0,0 +1,42 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=firmware-utils
+PKG_RELEASE:=1
+
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_URL=$(PROJECT_GIT)/project/firmware-utils.git
+PKG_SOURCE_DATE:=2024-10-16
+PKG_SOURCE_VERSION:=88fbd52666e3b3f83ebab40f95b84f265824a729
+PKG_MIRROR_HASH:=4809421286257a91b2f29e79b7bbd0852a72c6e82169b340036cca5703881232
+
+PKG_FLAGS:=nonshared
+PKG_BUILD_DEPENDS:=openssl zlib
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/cmake.mk
+
+define Package/default
+  SECTION:=utils
+  CATEGORY:=Base system
+  TITLE:=Firmware utility $(1)
+  DEPENDS:=$(2)
+endef
+
+Package/oseama = $(call Package/default,oseama,@TARGET_bcm53xx)
+
+define Package/oseama/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/oseama $(1)/usr/bin/
+endef
+
+Package/otrx = $(call Package/default,otrx,@(TARGET_bcm47xx||TARGET_bcm53xx))
+
+define Package/otrx/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/otrx $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,oseama))
+$(eval $(call BuildPackage,otrx))
diff --git a/package/utils/fitblk/Makefile b/package/utils/fitblk/Makefile
new file mode 100644
index 0000000..325963d
--- /dev/null
+++ b/package/utils/fitblk/Makefile
@@ -0,0 +1,42 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=fitblk
+PKG_RELEASE:=2
+PKG_LICENSE:=GPL-2.0-only
+PKG_MAINTAINER:=Daniel Golle <daniel@makrotopia.org>
+
+PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
+
+PKG_FLAGS:=nonshared
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/fitblk
+  HIDDEN:=1
+  SECTION:=base
+  CATEGORY:=Base system
+  TITLE:=fitblk firmware release tool
+endef
+
+define Package/fitblk/description
+Release uImage.FIT block devices using ioctl.
+endef
+
+define Build/Configure
+endef
+
+define Build/Compile
+	$(MAKE) -C $(PKG_BUILD_DIR) \
+		CC="$(TARGET_CC)" \
+		CFLAGS="$(TARGET_CFLAGS) -Wall -Werror" \
+		LDFLAGS="$(TARGET_LDFLAGS)"
+endef
+
+define Package/fitblk/install
+	$(INSTALL_DIR) $(1)/usr/sbin
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/fitblk $(1)/usr/sbin/
+	$(INSTALL_DIR) $(1)/lib/upgrade
+	$(INSTALL_DATA) ./files/fit.sh $(1)/lib/upgrade
+endef
+
+$(eval $(call BuildPackage,fitblk))
diff --git a/package/utils/fitblk/files/fit.sh b/package/utils/fitblk/files/fit.sh
new file mode 100644
index 0000000..b715a15
--- /dev/null
+++ b/package/utils/fitblk/files/fit.sh
@@ -0,0 +1,63 @@
+export_fitblk_bootdev() {
+	[ -e /sys/firmware/devicetree/base/chosen/rootdisk ] || return
+
+	local rootdisk="$(cat /sys/firmware/devicetree/base/chosen/rootdisk)"
+	local handle bootdev
+
+	for handle in /sys/class/mtd/mtd*/of_node/volumes/*/phandle; do
+		[ ! -e "$handle" ] && continue
+		if [ "$rootdisk" = "$(cat "$handle")" ]; then
+			if [ -e "${handle%/phandle}/volname" ]; then
+				export CI_KERNPART="$(cat "${handle%/phandle}/volname")"
+			elif [ -e "${handle%/phandle}/volid" ]; then
+				export CI_KERNVOLID="$(cat "${handle%/phandle}/volid")"
+			else
+				return
+			fi
+			export CI_UBIPART="$(cat "${handle%%/of_node*}/name")"
+			export CI_METHOD="ubi"
+			return
+		fi
+	done
+
+	for handle in /sys/class/mtd/mtd*/of_node/phandle; do
+		[ ! -e "$handle" ] && continue
+		if [ "$rootdisk" = "$(cat $handle)" ]; then
+			bootdev="${handle%/of_node/phandle}"
+			bootdev="${bootdev#/sys/class/mtd/}"
+			export PART_NAME="/dev/$bootdev"
+			export CI_METHOD="default"
+			return
+		fi
+	done
+
+	for handle in /sys/class/block/*/of_node/phandle; do
+		[ ! -e "$handle" ] && continue
+		if [ "$rootdisk" = "$(cat $handle)" ]; then
+			bootdev="${handle%/of_node/phandle}"
+			bootdev="${bootdev#/sys/class/block/}"
+			export EMMC_KERN_DEV="/dev/$bootdev"
+			export CI_METHOD="emmc"
+			return
+		fi
+	done
+}
+
+fit_do_upgrade() {
+	export_fitblk_bootdev
+	[ -n "$CI_METHOD" ] || return 1
+	[ -e /dev/fit0 ] && fitblk /dev/fit0
+	[ -e /dev/fitrw ] && fitblk /dev/fitrw
+
+	case "$CI_METHOD" in
+	emmc)
+		emmc_do_upgrade "$1"
+		;;
+	default)
+		default_do_upgrade "$1"
+		;;
+	ubi)
+		nand_do_upgrade "$1"
+		;;
+	esac
+}
diff --git a/package/utils/fitblk/src/Makefile b/package/utils/fitblk/src/Makefile
new file mode 100644
index 0000000..064764c
--- /dev/null
+++ b/package/utils/fitblk/src/Makefile
@@ -0,0 +1,7 @@
+all: fitblk
+
+fitblk:
+	$(CC) $(CFLAGS) -o $@ fitblk.c $(LDFLAGS)
+
+clean:
+	rm -f fitblk
diff --git a/package/utils/fitblk/src/fitblk.c b/package/utils/fitblk/src/fitblk.c
new file mode 100644
index 0000000..059ba60
--- /dev/null
+++ b/package/utils/fitblk/src/fitblk.c
@@ -0,0 +1,45 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <linux/fitblk.h>
+
+static int fitblk_release(char *device)
+{
+	int fd, ret;
+
+	fd = open(device, O_RDONLY);
+	if (fd == -1)
+		return errno;
+
+	ret = ioctl(fd, FITBLK_RELEASE, NULL);
+	close(fd);
+
+	if (ret == -1)
+		return errno;
+
+	return 0;
+}
+
+int main(int argc, char *argp[])
+{
+	int ret;
+
+	if (argc != 2) {
+		fprintf(stderr, "Release uImage.FIT sub-image block device\n");
+		fprintf(stderr, "Syntax: %s /dev/fitXXX\n", argp[0]);
+		return -EINVAL;
+	}
+
+	ret = fitblk_release(argp[1]);
+	if (ret)
+		fprintf(stderr, "fitblk: error releasing %s: %s\n", argp[1],
+			strerror(ret));
+	else
+		fprintf(stderr, "fitblk: %s released\n", argp[1]);
+
+	return ret;
+}
diff --git a/package/utils/fritz-tools/Makefile b/package/utils/fritz-tools/Makefile
new file mode 100644
index 0000000..6e20b56
--- /dev/null
+++ b/package/utils/fritz-tools/Makefile
@@ -0,0 +1,60 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=fritz-tools
+PKG_RELEASE:=2
+CMAKE_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/cmake.mk
+
+define Package/fritz-tools/Default
+  SECTION:=utils
+  CATEGORY:=Utilities
+endef
+
+define Package/fritz-tffs
+  $(call Package/fritz-tools/Default)
+  TITLE:=Utility to partially read the TFFS filesystems
+endef
+
+define Package/fritz-tffs/description
+ Utility to partially read the TFFS filesystems.
+endef
+
+define Package/fritz-tffs-nand
+  $(call Package/fritz-tools/Default)
+  TITLE:=Utility to partially read the TFFS filesystems on NAND flash
+endef
+
+define Package/fritz-tffs-nand/description
+ Utility to partially read the TFFS filesystems on NAND flash.
+endef
+
+define Package/fritz-caldata
+  $(call Package/fritz-tools/Default)
+  DEPENDS:=+zlib
+  TITLE:=Utility to extract WLAN calibration data
+endef
+
+define Package/fritz-caldata/description
+ Utility to extract the zlib compress calibration data from flash.
+endef
+
+define Package/fritz-tffs/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/fritz_tffs_read $(1)/usr/bin/fritz_tffs
+endef
+
+define Package/fritz-tffs-nand/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/fritz_tffs_nand_read $(1)/usr/bin/fritz_tffs_nand
+endef
+
+define Package/fritz-caldata/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/fritz_cal_extract $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,fritz-tffs))
+$(eval $(call BuildPackage,fritz-tffs-nand))
+$(eval $(call BuildPackage,fritz-caldata))
diff --git a/package/utils/fritz-tools/README.md b/package/utils/fritz-tools/README.md
new file mode 100644
index 0000000..def237b
--- /dev/null
+++ b/package/utils/fritz-tools/README.md
@@ -0,0 +1,50 @@
+Userspace utilties for accessing TFFS (a name-value storage usually found in AVM Fritz!Box based devices)
+
+## Building
+
+```
+mkdir build
+cd build
+cmake /path/to/fritz_tffs_tools
+make
+```
+
+## Usage
+
+All command line parameters are documented:
+```
+fritz_tffs_read -h
+```
+
+Show all entries from a TFFS partition dump  (in the format: name=value):
+```
+fritz_tffs_read -i /path/to/tffs.dump -a
+```
+
+Read a TFFS partition and show all entries (in the format: name=value):
+```
+fritz_tffs_read -i /dev/mtdX -a
+```
+
+Output only the value of a specific key (this will only show the value):
+```
+fritz_tffs_read -i /dev/mtdX -n my_ipaddress
+```
+
+## LICENSE
+
+See `LICENSE`:
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
diff --git a/package/utils/fritz-tools/src/CMakeLists.txt b/package/utils/fritz-tools/src/CMakeLists.txt
new file mode 100644
index 0000000..85b8157
--- /dev/null
+++ b/package/utils/fritz-tools/src/CMakeLists.txt
@@ -0,0 +1,16 @@
+cmake_minimum_required(VERSION 2.6)
+
+PROJECT(fritz-tools C)
+ADD_DEFINITIONS(-Wall -Werror --std=gnu99 -Wmissing-declarations)
+
+SET(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
+
+FIND_PATH(zlib_include_dir zlib.h)
+INCLUDE_DIRECTORIES(${zlib_include_dir})
+
+ADD_EXECUTABLE(fritz_tffs_read fritz_tffs_read.c)
+ADD_EXECUTABLE(fritz_tffs_nand_read fritz_tffs_nand_read.c)
+ADD_EXECUTABLE(fritz_cal_extract fritz_cal_extract.c)
+TARGET_LINK_LIBRARIES(fritz_cal_extract z)
+
+INSTALL(TARGETS fritz_tffs_read fritz_tffs_nand_read fritz_cal_extract RUNTIME DESTINATION bin)
diff --git a/package/utils/fritz-tools/src/fritz_cal_extract.c b/package/utils/fritz-tools/src/fritz_cal_extract.c
new file mode 100644
index 0000000..9899cd5
--- /dev/null
+++ b/package/utils/fritz-tools/src/fritz_cal_extract.c
@@ -0,0 +1,261 @@
+/*
+ * A tool for reading the zlib compressed calibration data
+ * found in AVM Fritz!Box based devices).
+ *
+ * Copyright (c) 2017 Christian Lamparter <chunkeey@googlemail.com>
+ *
+ * Based on zpipe, which is an example of proper use of zlib's inflate().
+ * that is Not copyrighted -- provided to the public domain
+ * Version 1.4  11 December 2005  Mark Adler
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <endian.h>
+#include <errno.h>
+#include "zlib.h"
+
+#define CHUNK 1024
+
+static inline size_t special_min(size_t a, size_t b)
+{
+	return a == 0 ? b : (a < b ? a : b);
+}
+
+/* Decompress from file source to file dest until stream ends or EOF.
+   inf() returns Z_OK on success, Z_MEM_ERROR if memory could not be
+   allocated for processing, Z_DATA_ERROR if the deflate data is
+   invalid or incomplete, Z_VERSION_ERROR if the version of zlib.h and
+   the version of the library linked do not match, or Z_ERRNO if there
+   is an error reading or writing the files. */
+static int inf(FILE *source, FILE *dest, size_t limit, size_t skip)
+{
+	int ret;
+	size_t have;
+	z_stream strm;
+	unsigned char in[CHUNK];
+	unsigned char out[CHUNK];
+
+	/* allocate inflate state */
+	strm.zalloc = Z_NULL;
+	strm.zfree = Z_NULL;
+	strm.opaque = Z_NULL;
+	strm.avail_in = 0;
+	strm.next_in = Z_NULL;
+	ret = inflateInit(&strm);
+	if (ret != Z_OK)
+		return ret;
+
+	/* decompress until deflate stream ends or end of file */
+	do {
+		strm.avail_in = fread(in, 1, CHUNK, source);
+		if (ferror(source)) {
+			(void)inflateEnd(&strm);
+			return Z_ERRNO;
+		}
+		if (strm.avail_in == 0)
+			break;
+		strm.next_in = in;
+
+		/* run inflate() on input until output buffer not full */
+		do {
+			strm.avail_out = CHUNK;
+			strm.next_out = out;
+			ret = inflate(&strm, Z_NO_FLUSH);
+			assert(ret != Z_STREAM_ERROR);  /* state not clobbered */
+			switch (ret) {
+			case Z_NEED_DICT:
+				ret = Z_DATA_ERROR;     /* and fall through */
+			case Z_DATA_ERROR:
+			case Z_MEM_ERROR:
+				(void)inflateEnd(&strm);
+				return ret;
+			}
+			have = special_min(limit, CHUNK - strm.avail_out) - skip;
+			if (fwrite(&out[skip], have, 1, dest) != 1 || ferror(dest)) {
+				(void)inflateEnd(&strm);
+				return Z_ERRNO;
+			}
+		skip = 0;
+		limit -= have;
+		} while (strm.avail_out == 0 && limit > 0);
+
+		/* done when inflate() says it's done */
+	} while (ret != Z_STREAM_END && limit > 0);
+
+	/* clean up and return */
+	(void)inflateEnd(&strm);
+	return (limit == 0 ? Z_OK : (ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR));
+}
+
+/* report a zlib or i/o error */
+static void zerr(int ret)
+{
+	switch (ret) {
+	case Z_ERRNO:
+		if (ferror(stdin))
+			fputs("error reading stdin\n", stderr);
+		if (ferror(stdout))
+			fputs("error writing stdout\n", stderr);
+		break;
+	case Z_STREAM_ERROR:
+		fputs("invalid compression level\n", stderr);
+		break;
+	case Z_DATA_ERROR:
+		fputs("invalid or incomplete deflate data\n", stderr);
+		break;
+	case Z_MEM_ERROR:
+		fputs("out of memory\n", stderr);
+		break;
+	case Z_VERSION_ERROR:
+		fputs("zlib version mismatch!\n", stderr);
+	}
+}
+
+static unsigned int get_num(char *str)
+{
+	if (!strncmp("0x", str, 2))
+		return strtoul(str+2, NULL, 16);
+	else
+		return strtoul(str, NULL, 10);
+}
+
+static void usage(void)
+{
+	fprintf(stderr, "Usage: fritz_cal_extract [-s seek offset] [-i skip] [-o output file] [-l limit] [infile] -e entry_id\n"
+			"Finds and extracts zlib compressed calibration data in the EVA loader\n");
+	exit(EXIT_FAILURE);
+}
+
+struct cal_entry {
+	uint16_t id;
+	uint16_t len;
+} __attribute__((packed));
+
+/* compress or decompress from stdin to stdout */
+int main(int argc, char **argv)
+{
+	struct cal_entry cal = { .len = 0 };
+	FILE *in = stdin;
+	FILE *out = stdout;
+	size_t limit = 0, skip = 0;
+	int initial_offset = 0;
+	int entry = -1;
+	int ret;
+	int opt;
+
+	while ((opt = getopt(argc, argv, "s:e:o:l:i:")) != -1) {
+		switch (opt) {
+		case 's':
+			initial_offset = (int)get_num(optarg);
+			if (errno) {
+				perror("Failed to parse seek offset");
+				goto out_bad;
+			}
+			break;
+		case 'e':
+			entry = (int) htobe16(get_num(optarg));
+			if (errno) {
+				perror("Failed to entry id");
+				goto out_bad;
+			}
+			break;
+		case 'o':
+			out = fopen(optarg, "w");
+			if (!out) {
+				perror("Failed to create output file");
+				goto out_bad;
+			}
+			break;
+		case 'l':
+			limit = (size_t)get_num(optarg);
+			if (errno) {
+				perror("Failed to parse limit");
+				goto out_bad;
+			}
+			break;
+		case 'i':
+			skip = (size_t)get_num(optarg);
+			if (errno) {
+				perror("Failed to parse skip");
+				goto out_bad;
+			}
+			break;
+		default: /* '?' */
+			usage();
+		}
+	}
+
+	if (entry == -1)
+		usage();
+
+	if (argc > 1 && optind <= argc) {
+		in = fopen(argv[optind], "r");
+		if (!in) {
+			perror("Failed to open input file");
+			goto out_bad;
+		}
+	}
+
+	if (initial_offset) {
+		ret = fseek(in, initial_offset, SEEK_CUR);
+		if (ret) {
+			perror("Failed to seek to calibration table");
+			goto out_bad;
+		}
+	}
+
+	do {
+		ret = fseek(in, be16toh(cal.len), SEEK_CUR);
+		if (feof(in)) {
+			fprintf(stderr, "Reached end of file, but didn't find the matching entry\n");
+			goto out_bad;
+		} else if (ferror(in)) {
+			perror("Failure during seek");
+			goto out_bad;
+		}
+
+		ret = fread(&cal, 1, sizeof cal, in);
+		if (ret != sizeof cal)
+			goto out_bad;
+	} while (entry != cal.id || cal.id == 0xffff);
+
+	if (cal.id == 0xffff) {
+		fprintf(stderr, "Reached end of filesystem, but didn't find the matching entry\n");
+		goto out_bad;
+	}
+
+	ret = inf(in, out, limit, skip);
+	if (ret == Z_OK)
+		goto out;
+
+	zerr(ret);
+
+out_bad:
+	ret = EXIT_FAILURE;
+
+out:
+	if (in)
+		fclose(in);
+	if (out)
+		fclose(out);
+	return ret;
+}
diff --git a/package/utils/fritz-tools/src/fritz_tffs_nand_read.c b/package/utils/fritz-tools/src/fritz_tffs_nand_read.c
new file mode 100644
index 0000000..05179bb
--- /dev/null
+++ b/package/utils/fritz-tools/src/fritz_tffs_nand_read.c
@@ -0,0 +1,587 @@
+/*
+ * A tool for reading the TFFS partitions (a name-value storage usually
+ * found in AVM Fritz!Box based devices) on nand flash.
+ *
+ * Copyright (c) 2018 Valentin Spreckels <Valentin.Spreckels@Informatik.Uni-Oldenburg.DE>
+ *
+ * Based on the fritz_tffs_read tool:
+ *     Copyright (c) 2015-2016 Martin Blumenstingl <martin.blumenstingl@googlemail.com>
+ * and on the TFFS 2.0 kernel driver from AVM:
+ *     Copyright (c) 2004-2007 AVM GmbH <fritzbox_info@avm.de>
+ * and the TFFS 3.0 kernel driver from AVM:
+ *     Copyright (C) 2004-2014 AVM GmbH <fritzbox_info@avm.de>
+ * and the OpenWrt TFFS kernel driver:
+ *     Copyright (c) 2013 John Crispin <john@phrozen.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <libgen.h>
+#include <getopt.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <endian.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <arpa/inet.h>
+#include <mtd/mtd-user.h>
+#include <assert.h>
+
+#define DEFAULT_TFFS_SIZE	(256 * 1024)
+
+#define TFFS_ID_END		0xffffffff
+#define TFFS_ID_TABLE_NAME	0x000001ff
+
+#define TFFS_BLOCK_HEADER_MAGIC	0x41564d5f54464653ULL
+#define TFFS_VERSION		0x0003
+#define TFFS_ENTRY_HEADER_SIZE	0x18
+#define TFFS_MAXIMUM_SEGMENT_SIZE	(0x800 - TFFS_ENTRY_HEADER_SIZE)
+
+#define TFFS_SECTOR_SIZE 0x0800
+#define TFFS_SECTOR_OOB_SIZE 0x0040
+#define TFFS_SECTORS_PER_PAGE 2
+
+#define TFFS_SEGMENT_CLEARED 0xffffffff
+
+static char *progname;
+static char *mtddev;
+static char *name_filter = NULL;
+static bool show_all = false;
+static bool print_all_key_names = false;
+static bool read_oob_sector_health = false;
+static bool swap_bytes = false;
+static uint8_t readbuf[TFFS_SECTOR_SIZE];
+static uint8_t oobbuf[TFFS_SECTOR_OOB_SIZE];
+static uint32_t blocksize;
+static int mtdfd;
+static uint32_t num_sectors;
+static uint8_t *sectors;
+static uint32_t *sector_ids;
+
+static inline void sector_mark_bad(int num)
+{
+	sectors[num / 8] &= ~(0x80 >> (num % 8));
+};
+
+static inline uint8_t sector_get_good(int num)
+{
+	return sectors[num / 8] & 0x80 >> (num % 8);
+};
+
+struct tffs_entry_segment {
+	uint32_t len;
+	void *val;
+};
+
+struct tffs_entry {
+	uint32_t len;
+	void *val;
+};
+
+struct tffs_name_table_entry {
+	uint32_t id;
+	char *val;
+};
+
+struct tffs_key_name_table {
+	uint32_t size;
+	struct tffs_name_table_entry *entries;
+};
+
+static inline uint8_t read_uint8(void *buf, ptrdiff_t off)
+{
+	return *(uint8_t *)(buf + off);
+}
+
+static inline uint32_t read_uint32(void *buf, ptrdiff_t off)
+{
+	uint32_t tmp = *(uint32_t *)(buf + off);
+	if (swap_bytes) {
+		tmp = be32toh(tmp);
+	}
+	return tmp;
+}
+
+static inline uint64_t read_uint64(void *buf, ptrdiff_t off)
+{
+	uint64_t tmp = *(uint64_t *)(buf + off);
+	if (swap_bytes) {
+		tmp = be64toh(tmp);
+	}
+	return tmp;
+}
+
+static int read_sector(off_t pos)
+{
+	if (pread(mtdfd, readbuf, TFFS_SECTOR_SIZE, pos) != TFFS_SECTOR_SIZE) {
+		return -1;
+	}
+
+	sector_ids[pos / TFFS_SECTOR_SIZE] = read_uint32(readbuf, 0x00);
+
+	return 0;
+}
+
+static int read_sectoroob(off_t pos)
+{
+	struct mtd_oob_buf oob = {
+		.start = pos,
+		.length = TFFS_SECTOR_OOB_SIZE,
+		.ptr = oobbuf
+	};
+
+	if (ioctl(mtdfd, MEMREADOOB, &oob) < 0)	{
+		return -1;
+	}
+
+	return 0;
+}
+
+static inline uint32_t get_walk_size(uint32_t entry_len)
+{
+	return (entry_len + 3) & ~0x03;
+}
+
+static void print_entry_value(const struct tffs_entry *entry)
+{
+	/* These are NOT NULL terminated. */
+	fwrite(entry->val, 1, entry->len, stdout);
+}
+
+static int find_entry(uint32_t id, struct tffs_entry *entry)
+{
+	uint32_t rev = 0;
+	uint32_t num_segments = 0;
+	struct tffs_entry_segment *segments = NULL;
+
+	off_t pos = 0;
+	uint8_t block_end = 0;
+	for (uint32_t sector = 0; sector < num_sectors; sector++, pos += TFFS_SECTOR_SIZE) {
+		if (block_end) {
+			if (pos % blocksize == 0) {
+				block_end = 0;
+			}
+		} else if (sector_get_good(sector)) {
+			if (sector_ids[sector]) {
+				if (sector_ids[sector] == TFFS_ID_END) {
+					/* no more entries in this block */
+					block_end = 1;
+					continue;
+				}
+
+				if (sector_ids[sector] != id)
+					continue;
+			}
+
+			if (read_sectoroob(pos) || read_sector(pos)) {
+				fprintf(stderr, "ERROR: sector isn't readable, but has been previously!\n");
+				exit(EXIT_FAILURE);
+			}
+			uint32_t read_id = read_uint32(readbuf, 0x00);
+			uint32_t read_len = read_uint32(readbuf, 0x04);
+			uint32_t read_rev = read_uint32(readbuf, 0x0c);
+			if (read_oob_sector_health) {
+				uint32_t oob_id = read_uint32(oobbuf, 0x02);
+				uint32_t oob_len = read_uint32(oobbuf, 0x06);
+				uint32_t oob_rev = read_uint32(oobbuf, 0x0a);
+
+				if (oob_id != read_id || oob_len != read_len || oob_rev != read_rev) {
+					fprintf(stderr, "Warning: sector has inconsistent metadata\n");
+					continue;
+				}
+			}
+			if (read_id == TFFS_ID_END) {
+				/* no more entries in this block */
+				block_end = 1;
+				continue;
+			}
+			if (read_len > TFFS_MAXIMUM_SEGMENT_SIZE) {
+				fprintf(stderr, "Warning: segment is longer than possible\n");
+				continue;
+			}
+			if (read_id == id) {
+				if (read_rev < rev) {
+					/* obsolete revision => ignore this */
+					continue;
+				}
+				if (read_rev > rev) {
+					/* newer revision => clear old data */
+					for (uint32_t i = 0; i < num_segments; i++) {
+						free(segments[i].val);
+					}
+					free (segments);
+					rev = read_rev;
+					num_segments = 0;
+					segments = NULL;
+				}
+
+				uint32_t seg = read_uint32(readbuf, 0x10);
+
+				if (seg == TFFS_SEGMENT_CLEARED) {
+					continue;
+				}
+
+				uint32_t next_seg = read_uint32(readbuf, 0x14);
+
+				uint32_t new_num_segs = next_seg == 0 ? seg + 1 : next_seg + 1;
+				if (new_num_segs > num_segments) {
+					segments = realloc(segments, new_num_segs * sizeof(struct tffs_entry_segment));
+					memset(segments + (num_segments * sizeof(struct tffs_entry_segment)), 0x0,
+							(new_num_segs - num_segments) * sizeof(struct tffs_entry_segment));
+					num_segments = new_num_segs;
+				}
+				segments[seg].len = read_len;
+				segments[seg].val = malloc(read_len);
+				memcpy(segments[seg].val, readbuf + TFFS_ENTRY_HEADER_SIZE, read_len);
+			}
+		}
+	}
+
+	if (num_segments == 0) {
+		return 0;
+	}
+
+	assert (segments != NULL);
+
+	uint32_t len = 0;
+	for (uint32_t i = 0; i < num_segments; i++) {
+		if (segments[i].val == NULL) {
+			/* missing segment */
+			return 0;
+		}
+
+		len += segments[i].len;
+	}
+
+	void *p = malloc(len);
+	entry->val = p;
+	entry->len = len;
+	for (uint32_t i = 0; i < num_segments; i++) {
+		memcpy(p, segments[i].val, segments[i].len);
+		p += segments[i].len;
+	}
+
+	return 1;
+}
+
+static void parse_key_names(struct tffs_entry *names_entry,
+			     struct tffs_key_name_table *key_names)
+{
+	uint32_t pos = 0, i = 0;
+	struct tffs_name_table_entry *name_item;
+
+	key_names->entries = NULL;
+
+	do {
+		key_names->entries = realloc(key_names->entries,
+			 sizeof(struct tffs_name_table_entry) * (i + 1));
+		if (key_names->entries == NULL) {
+			fprintf(stderr, "ERROR: memory allocation failed!\n");
+			exit(EXIT_FAILURE);
+		}
+		name_item = &key_names->entries[i];
+
+		name_item->id = read_uint32(names_entry->val, pos);
+		pos += sizeof(uint32_t);
+		name_item->val = strdup((const char *)(names_entry->val + pos));
+
+		/*
+		 * There is no "length" field because the string values are
+		 * simply NULL-terminated -> strlen() gives us the size.
+		 */
+		pos += get_walk_size(strlen(name_item->val) + 1);
+
+		++i;
+	} while (pos < names_entry->len);
+
+	key_names->size = i;
+}
+
+static void show_all_key_names(struct tffs_key_name_table *key_names)
+{
+	for (uint32_t i = 0; i < key_names->size; i++)
+		printf("%s\n", key_names->entries[i].val);
+}
+
+static int show_all_key_value_pairs(struct tffs_key_name_table *key_names)
+{
+	uint8_t has_value = 0;
+	struct tffs_entry tmp;
+
+	for (uint32_t i = 0; i < key_names->size; i++) {
+		if (find_entry(key_names->entries[i].id, &tmp)) {
+			printf("%s=", (const char *)key_names->entries[i].val);
+			print_entry_value(&tmp);
+			printf("\n");
+			has_value++;
+			free(tmp.val);
+		}
+	}
+
+	if (!has_value) {
+		fprintf(stderr, "ERROR: no values found!\n");
+		return EXIT_FAILURE;
+	}
+
+	return EXIT_SUCCESS;
+}
+
+static int show_matching_key_value(struct tffs_key_name_table *key_names)
+{
+	struct tffs_entry tmp;
+	const char *name;
+
+	for (uint32_t i = 0; i < key_names->size; i++) {
+		name = key_names->entries[i].val;
+
+		if (strcmp(name, name_filter) == 0) {
+			if (find_entry(key_names->entries[i].id, &tmp)) {
+				print_entry_value(&tmp);
+				printf("\n");
+				free(tmp.val);
+				return EXIT_SUCCESS;
+			} else {
+				fprintf(stderr,
+					"ERROR: no value found for name %s!\n",
+					name);
+				return EXIT_FAILURE;
+			}
+		}
+	}
+
+	fprintf(stderr, "ERROR: Unknown key name %s!\n", name_filter);
+	return EXIT_FAILURE;
+}
+
+static int check_sector(off_t pos)
+{
+	if (!read_oob_sector_health) {
+		return 1;
+	}
+	if (read_sectoroob(pos)) {
+		return 0;
+	}
+	if (read_uint8(oobbuf, 0x00) != 0xff) {
+		/* block is bad */
+		return 0;
+	}
+	if (read_uint8(oobbuf, 0x01) != 0xff) {
+		/* sector is bad */
+		return 0;
+	}
+	return 1;
+}
+
+static int check_block(off_t pos, uint32_t sector)
+{
+	if (!check_sector(pos)) {
+		return 0;
+	}
+	if (read_sector(pos)) {
+		return 0;
+	}
+	if (read_uint64(readbuf, 0x00) != TFFS_BLOCK_HEADER_MAGIC) {
+		fprintf(stderr, "Warning: block without magic header. Skipping block\n");
+		return 0;
+	}
+	if (read_uint32(readbuf, 0x0c) != TFFS_SECTORS_PER_PAGE) {
+		fprintf(stderr, "Warning: block with wrong number of sectors per page. Skipping block\n");
+		return 0;
+	}
+
+	uint32_t num_hdr_bad = read_uint32(readbuf, 0x0c);
+	for (uint32_t i = 0; i < num_hdr_bad; i++) {
+		uint32_t bad = sector + read_uint64(readbuf, 0x1c + sizeof(uint64_t)*i);
+		sector_mark_bad(bad);
+	}
+
+	return 1;
+}
+
+static int scan_mtd(void)
+{
+	struct mtd_info_user info;
+
+	if (ioctl(mtdfd, MEMGETINFO, &info)) {
+		return 0;
+	}
+
+	blocksize = info.erasesize;
+
+	num_sectors = info.size / TFFS_SECTOR_SIZE;
+	sectors = malloc((num_sectors + 7) / 8);
+	sector_ids = calloc(num_sectors, sizeof(uint32_t));
+	if (!sectors || !sector_ids) {
+		fprintf(stderr, "ERROR: memory allocation failed!\n");
+		exit(EXIT_FAILURE);
+	}
+	memset(sectors, 0xff, (num_sectors + 7) / 8);
+
+	uint32_t sector = 0, valid_blocks = 0;
+	uint8_t block_ok = 0;
+	for (off_t pos = 0; pos < info.size; sector++, pos += TFFS_SECTOR_SIZE) {
+		if (pos % info.erasesize == 0) {
+			block_ok = check_block(pos, sector);
+			/* first sector of the block contains metadata
+			   => handle it like a bad sector */
+			sector_mark_bad(sector);
+			if (block_ok) {
+				valid_blocks++;
+			}
+		} else if (!block_ok || !sector_get_good(sector) || !check_sector(pos)) {
+			sector_mark_bad(sector);
+		}
+	}
+
+	return valid_blocks;
+}
+
+static void usage(int status)
+{
+	FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout;
+
+	fprintf(stream, "Usage: %s [OPTIONS...]\n", progname);
+	fprintf(stream,
+	"\n"
+	"Options:\n"
+	"  -a              list all key value pairs found in the TFFS file/device\n"
+	"  -d <mtd>        inspect the TFFS on mtd device <mtd>\n"
+	"  -h              show this screen\n"
+	"  -l              list all supported keys\n"
+	"  -n <key name>   display the value of the given key\n"
+	"  -o              read OOB information about sector health\n"
+	);
+
+	exit(status);
+}
+
+static void parse_options(int argc, char *argv[])
+{
+	while (1) {
+		int c;
+
+		c = getopt(argc, argv, "abd:hln:o");
+		if (c == -1)
+			break;
+
+		switch (c) {
+		case 'a':
+			show_all = true;
+			name_filter = NULL;
+			print_all_key_names = false;
+			break;
+		case 'b':
+			swap_bytes = 1;
+			break;
+		case 'd':
+			mtddev = optarg;
+			break;
+		case 'h':
+			usage(EXIT_SUCCESS);
+			break;
+		case 'l':
+			print_all_key_names = true;
+			show_all = false;
+			name_filter = NULL;
+			break;
+		case 'n':
+			name_filter = optarg;
+			show_all = false;
+			print_all_key_names = false;
+			break;
+		case 'o':
+			read_oob_sector_health = true;
+			break;
+		default:
+			usage(EXIT_FAILURE);
+			break;
+		}
+	}
+
+	if (!mtddev) {
+		fprintf(stderr, "ERROR: No input file (-d <file>) given!\n");
+		usage(EXIT_FAILURE);
+	}
+
+	if (!show_all && !name_filter && !print_all_key_names) {
+		fprintf(stderr,
+			"ERROR: either -l, -a or -n <key name> is required!\n");
+		usage(EXIT_FAILURE);
+	}
+}
+
+int main(int argc, char *argv[])
+{
+	int ret = EXIT_FAILURE;
+	struct tffs_entry name_table;
+	struct tffs_key_name_table key_names;
+
+	progname = basename(argv[0]);
+
+	parse_options(argc, argv);
+
+	mtdfd = open(mtddev, O_RDONLY);
+	if (mtdfd < 0) {
+		fprintf(stderr, "ERROR: Failed to open tffs device %s\n",
+			mtddev);
+		goto out;
+	}
+
+	if (!scan_mtd()) {
+		fprintf(stderr, "ERROR: Parsing blocks from tffs device %s failed\n", mtddev);
+		fprintf(stderr, "       Is byte-swapping (-b) required?\n");
+		goto out_close;
+	}
+
+	if (!find_entry(TFFS_ID_TABLE_NAME, &name_table)) {
+		fprintf(stderr, "ERROR: No name table found on tffs device %s\n",
+			mtddev);
+		goto out_free_sectors;
+	}
+
+	parse_key_names(&name_table, &key_names);
+	if (key_names.size < 1) {
+		fprintf(stderr, "ERROR: No name table found on tffs device %s\n",
+			mtddev);
+		goto out_free_entry;
+	}
+
+	if (print_all_key_names) {
+		show_all_key_names(&key_names);
+		ret = EXIT_SUCCESS;
+	} else if (show_all) {
+		ret = show_all_key_value_pairs(&key_names);
+	} else {
+		ret = show_matching_key_value(&key_names);
+	}
+
+	free(key_names.entries);
+out_free_entry:
+	free(name_table.val);
+out_free_sectors:
+	free(sector_ids);
+	free(sectors);
+out_close:
+	close(mtdfd);
+out:
+	return ret;
+}
diff --git a/package/utils/fritz-tools/src/fritz_tffs_read.c b/package/utils/fritz-tools/src/fritz_tffs_read.c
new file mode 100644
index 0000000..256c34c
--- /dev/null
+++ b/package/utils/fritz-tools/src/fritz_tffs_read.c
@@ -0,0 +1,379 @@
+/*
+ * A tool for reading the TFFS partitions (a name-value storage usually
+ * found in AVM Fritz!Box based devices).
+ *
+ * Copyright (c) 2015-2016 Martin Blumenstingl <martin.blumenstingl@googlemail.com>
+ *
+ * Based on the TFFS 2.0 kernel driver from AVM:
+ *     Copyright (c) 2004-2007 AVM GmbH <fritzbox_info@avm.de>
+ * and the OpenWrt TFFS kernel driver:
+ *     Copyright (c) 2013 John Crispin <blogic@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <libgen.h>
+#include <getopt.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <arpa/inet.h>
+
+#define TFFS_ID_END		0xffff
+#define TFFS_ID_TABLE_NAME	0x01ff
+
+static char *progname;
+static char *input_file;
+static unsigned long tffs_size;
+static char *name_filter = NULL;
+static bool show_all = false;
+static bool print_all_key_names = false;
+static bool swap_bytes = false;
+
+struct tffs_entry_header {
+	uint16_t id;
+	uint16_t len;
+};
+
+struct tffs_entry {
+	const struct tffs_entry_header *header;
+	char *name;
+	uint8_t *val;
+};
+
+struct tffs_name_table_entry {
+	const uint32_t *id;
+	const char *val;
+};
+
+struct tffs_key_name_table {
+	uint32_t size;
+	struct tffs_name_table_entry *entries;
+};
+
+static inline uint16_t get_header_len(const struct tffs_entry_header *header)
+{
+	if (swap_bytes)
+		return ntohs(header->len);
+
+	return header->len;
+}
+
+static inline uint16_t get_header_id(const struct tffs_entry_header *header)
+{
+	if (swap_bytes)
+		return ntohs(header->id);
+
+	return header->id;
+}
+
+static inline uint16_t to_entry_header_id(uint32_t name_id)
+{
+	if (swap_bytes)
+		return ntohl(name_id) & 0xffff;
+
+	return name_id & 0xffff;
+}
+
+static inline uint32_t get_walk_size(uint32_t entry_len)
+{
+	return (entry_len + 3) & ~0x03;
+}
+
+static void print_entry_value(const struct tffs_entry *entry)
+{
+	int i;
+
+	/* These are NOT NULL terminated. */
+	for (i = 0; i < get_header_len(entry->header); i++)
+		fprintf(stdout, "%c", entry->val[i]);
+}
+
+static void parse_entry(uint8_t *buffer, uint32_t pos,
+			struct tffs_entry *entry)
+{
+	entry->header = (struct tffs_entry_header *) &buffer[pos];
+	entry->val = &buffer[pos + sizeof(struct tffs_entry_header)];
+}
+
+static int find_entry(uint8_t *buffer, uint16_t id, struct tffs_entry *entry)
+{
+	uint32_t pos = 0;
+
+	do {
+		parse_entry(buffer, pos, entry);
+
+		if (get_header_id(entry->header) == id)
+			return 1;
+
+		pos += sizeof(struct tffs_entry_header);
+		pos += get_walk_size(get_header_len(entry->header));
+	} while (pos < tffs_size && entry->header->id != TFFS_ID_END);
+
+	return 0;
+}
+
+static void parse_key_names(struct tffs_entry *names_entry,
+			    struct tffs_key_name_table *key_names)
+{
+	uint32_t pos = 0, i = 0;
+	struct tffs_name_table_entry *name_item;
+
+	key_names->entries = calloc(sizeof(*name_item), 1);
+
+	do {
+		name_item = &key_names->entries[i];
+
+		name_item->id = (uint32_t *) &names_entry->val[pos];
+		pos += sizeof(*name_item->id);
+		name_item->val = (const char *) &names_entry->val[pos];
+
+		/*
+		 * There is no "length" field because the string values are
+		 * simply NULL-terminated -> strlen() gives us the size.
+		 */
+		pos += get_walk_size(strlen(name_item->val) + 1);
+
+		++i;
+		key_names->entries = realloc(key_names->entries,
+						sizeof(*name_item) * (i + 1));
+	} while (pos < get_header_len(names_entry->header));
+
+	key_names->size = i;
+}
+
+static void show_all_key_names(struct tffs_key_name_table *key_names)
+{
+	int i;
+
+	for (i = 0; i < key_names->size; i++)
+		printf("%s\n", key_names->entries[i].val);
+}
+
+static int show_all_key_value_pairs(uint8_t *buffer,
+				    struct tffs_key_name_table *key_names)
+{
+	int i, has_value = 0;
+	uint16_t id;
+	struct tffs_entry tmp;
+
+	for (i = 0; i < key_names->size; i++) {
+		id = to_entry_header_id(*key_names->entries[i].id);
+
+		if (find_entry(buffer, id, &tmp)) {
+			printf("%s=", key_names->entries[i].val);
+			print_entry_value(&tmp);
+			printf("\n");
+			has_value++;
+		}
+	}
+
+	if (!has_value) {
+		fprintf(stderr, "ERROR: no values found!\n");
+		return EXIT_FAILURE;
+	}
+
+	return EXIT_SUCCESS;
+}
+
+static int show_matching_key_value(uint8_t *buffer,
+				   struct tffs_key_name_table *key_names)
+{
+	int i;
+	uint16_t id;
+	struct tffs_entry tmp;
+	const char *name;
+
+	for (i = 0; i < key_names->size; i++) {
+		name = key_names->entries[i].val;
+
+		if (strcmp(name, name_filter) == 0) {
+			id = to_entry_header_id(*key_names->entries[i].id);
+
+			if (find_entry(buffer, id, &tmp)) {
+				print_entry_value(&tmp);
+				printf("\n");
+				return EXIT_SUCCESS;
+			} else {
+				fprintf(stderr,
+					"ERROR: no value found for name %s!\n",
+					name);
+				return EXIT_FAILURE;
+			}
+		}
+	}
+
+	fprintf(stderr, "ERROR: Unknown key name %s!\n", name_filter);
+	return EXIT_FAILURE;
+}
+
+static void usage(int status)
+{
+	FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout;
+
+	fprintf(stream, "Usage: %s [OPTIONS...]\n", progname);
+	fprintf(stream,
+	"\n"
+	"Options:\n"
+	"  -a              list all key value pairs found in the TFFS file/device\n"
+	"  -b              swap bytes while parsing the TFFS file/device\n"
+	"  -h              show this screen\n"
+	"  -i <file>       inspect the given TFFS file/device <file>\n"
+	"  -l              list all supported keys\n"
+	"  -n <key name>   display the value of the given key\n"
+	"  -s <size>       the (max) size of the TFFS file/device <size>\n"
+	);
+
+	exit(status);
+}
+
+static int file_exist(char *filename)
+{
+	struct stat buffer;
+
+	return stat(filename, &buffer) == 0;
+}
+
+static void parse_options(int argc, char *argv[])
+{
+	while (1)
+	{
+		int c;
+
+		c = getopt(argc, argv, "abhi:ln:s:");
+		if (c == -1)
+			break;
+
+		switch (c) {
+			case 'a':
+				show_all = true;
+				name_filter = NULL;
+				print_all_key_names = false;
+				break;
+			case 'b':
+				swap_bytes = 1;
+				break;
+			case 'h':
+				usage(EXIT_SUCCESS);
+				break;
+			case 'i':
+				input_file = optarg;
+				break;
+			case 'l':
+				print_all_key_names = true;
+				show_all = false;
+				name_filter = NULL;
+				break;
+			case 'n':
+				name_filter = optarg;
+				show_all = false;
+				print_all_key_names = false;
+				break;
+			case 's':
+				tffs_size = strtoul(optarg, NULL, 0);
+				break;
+			default:
+				usage(EXIT_FAILURE);
+				break;
+		}
+	}
+
+	if (!input_file) {
+		fprintf(stderr, "ERROR: No input file (-i <file>) given!\n");
+		exit(EXIT_FAILURE);
+	}
+
+	if (!file_exist(input_file)) {
+		fprintf(stderr, "ERROR: %s does not exist\n", input_file);
+		exit(EXIT_FAILURE);
+	}
+
+	if (!show_all && !name_filter && !print_all_key_names) {
+		fprintf(stderr,
+			"ERROR: either -l, -a or -n <key name> is required!\n");
+		exit(EXIT_FAILURE);
+	}
+}
+
+int main(int argc, char *argv[])
+{
+	int ret = EXIT_FAILURE;
+	uint8_t *buffer;
+	FILE *fp;
+	struct tffs_entry name_table;
+	struct tffs_key_name_table key_names;
+
+	progname = basename(argv[0]);
+
+	parse_options(argc, argv);
+
+	fp = fopen(input_file, "r");
+
+	if (!fp) {
+		fprintf(stderr, "ERROR: Failed to open tffs input file %s\n",
+			input_file);
+		goto out;
+	}
+
+	if (tffs_size == 0) {
+		fseek(fp, 0L, SEEK_END);
+		tffs_size = ftell(fp);
+		fseek(fp, 0L, SEEK_SET);
+	}
+
+	buffer = malloc(tffs_size);
+
+	if (fread(buffer, 1, tffs_size, fp) != tffs_size) {
+		fprintf(stderr, "ERROR: Failed read tffs file %s\n",
+			input_file);
+		goto out_free;
+	}
+
+	if (!find_entry(buffer, TFFS_ID_TABLE_NAME, &name_table)) {
+		fprintf(stderr,"ERROR: No name table found in tffs file %s\n",
+			input_file);
+		fprintf(stderr,"       Is byte-swapping (-b) required?\n");
+		goto out_free;
+	}
+
+	parse_key_names(&name_table, &key_names);
+	if (key_names.size < 1) {
+		fprintf(stderr, "ERROR: No name table found in tffs file %s\n",
+			input_file);
+		goto out_free_names;
+	}
+
+	if (print_all_key_names) {
+		show_all_key_names(&key_names);
+		ret = EXIT_SUCCESS;
+	} else if (show_all) {
+		ret = show_all_key_value_pairs(buffer, &key_names);
+	} else {
+		ret = show_matching_key_value(buffer, &key_names);
+	}
+
+out_free_names:
+	free(key_names.entries);
+out_free:
+	fclose(fp);
+	free(buffer);
+out:
+	return ret;
+}
diff --git a/package/utils/hwdata/Makefile b/package/utils/hwdata/Makefile
new file mode 100644
index 0000000..0ced19e
--- /dev/null
+++ b/package/utils/hwdata/Makefile
@@ -0,0 +1,47 @@
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=hwdata
+PKG_VERSION:=0.359
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://codeload.github.com/vcrhonek/hwdata/tar.gz/v$(PKG_VERSION)?
+PKG_HASH:=07bf89f5a1b341427536b4fffe300c7848988367a1bce20fc4b1ab7e7629f861
+
+PKG_MAINTAINER:=
+PKG_LICENSE:=GPL-2.0-or-later  XFree86-1.0
+PKG_LICENSE_FILES:=LICENSE
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/pciids
+  SECTION:=utils
+  CATEGORY:=Utilities
+  TITLE:=PCI ID list
+  URL:=https://github.com/vcrhonek/hwdata
+endef
+
+define Package/usbids
+  SECTION:=utils
+  CATEGORY:=Utilities
+  TITLE:=USB ID list
+  URL:=https://github.com/vcrhonek/hwdata
+endef
+
+define Package/pciids/install
+	$(INSTALL_DIR) $(1)/usr/share/hwdata
+	$(INSTALL_DATA) $(PKG_BUILD_DIR)/pci.ids $(1)/usr/share/hwdata
+endef
+
+define Package/usbids/install
+	$(INSTALL_DIR) $(1)/usr/share/hwdata
+	$(INSTALL_DATA) $(PKG_BUILD_DIR)/usb.ids $(1)/usr/share/hwdata
+endef
+
+$(eval $(call BuildPackage,pciids))
+$(eval $(call BuildPackage,usbids))
diff --git a/package/utils/jboot-tools/Makefile b/package/utils/jboot-tools/Makefile
new file mode 100644
index 0000000..ce9758b
--- /dev/null
+++ b/package/utils/jboot-tools/Makefile
@@ -0,0 +1,28 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=jboot-tools
+PKG_RELEASE:=1
+CMAKE_INSTALL:=1
+PKG_FLAGS:=nonshared
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/cmake.mk
+
+define Package/jboot-tools
+  SECTION:=firmware
+  CATEGORY:=Firmware
+  DEPENDS:=@TARGET_ramips
+  TITLE:=Utilites for accessing JBOOT based D-Link devices Calibration data
+endef
+
+define Package/jboot-tools/description
+ This package contains:
+ jboot_config_read.c: partially read the config partition of JBOOT based D-Link devices.
+endef
+
+define Package/jboot-tools/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/jboot_config_read $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,jboot-tools))
diff --git a/package/utils/jboot-tools/README.md b/package/utils/jboot-tools/README.md
new file mode 100644
index 0000000..0d1aeac
--- /dev/null
+++ b/package/utils/jboot-tools/README.md
@@ -0,0 +1,46 @@
+Userspace utilties for jboot based devices config partition read
+
+## Building
+
+```
+mkdir build
+cd build
+cmake /path/to/jboot-tools
+make
+```
+
+## Usage
+
+All command line parameters are documented:
+```
+jboot_config_read -h
+```
+
+Show all stored MACs:
+```
+jboot_config_read -m -i PATH_TO_CONFIG_PARTITIO
+```
+
+Extract wifi eeprom data:
+```
+jboot_config_read  -i PATH_TO_CONFIG_PARTITION -e OUTPUT_PATH
+```
+
+
+## LICENSE
+
+See `LICENSE`:
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
diff --git a/package/utils/jboot-tools/src/CMakeLists.txt b/package/utils/jboot-tools/src/CMakeLists.txt
new file mode 100644
index 0000000..98fbab3
--- /dev/null
+++ b/package/utils/jboot-tools/src/CMakeLists.txt
@@ -0,0 +1,11 @@
+cmake_minimum_required(VERSION 2.6)
+
+PROJECT(jboot-tools C)
+ADD_DEFINITIONS(-Wall -Werror --std=gnu99 -Wmissing-declarations)
+
+SET(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
+
+ADD_EXECUTABLE(jboot_config_read jboot_config_read.c)
+TARGET_LINK_LIBRARIES(jboot_config_read)
+
+INSTALL(TARGETS jboot_config_read RUNTIME DESTINATION bin)
diff --git a/package/utils/jboot-tools/src/jboot_config_read.c b/package/utils/jboot-tools/src/jboot_config_read.c
new file mode 100644
index 0000000..c65b091
--- /dev/null
+++ b/package/utils/jboot-tools/src/jboot_config_read.c
@@ -0,0 +1,427 @@
+/*
+ * jboot_config_read
+ *
+ * Copyright (C) 2018 Paweł Dembicki <paweldembicki@gmail.com>
+ *
+ * This tool is based on mkdlinkfw.
+ * Copyright (C) 2018 Paweł Dembicki <paweldembicki@gmail.com>
+ * Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org>
+ * Copyright (C) 2008,2009 Wang Jian <lark@linux.net.cn>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>		/* for unlink() */
+#include <libgen.h>
+#include <getopt.h>		/* for getopt() */
+#include <stdarg.h>
+#include <stdbool.h>
+#include <endian.h>
+#include <errno.h>
+#include <sys/stat.h>
+
+
+
+#define ERR(fmt, ...) do { \
+	fflush(0); \
+	fprintf(stderr, "[%s] *** error: " fmt "\n", \
+			progname, ## __VA_ARGS__); \
+} while (0)
+
+#define ERRS(fmt, ...) do { \
+	int save = errno; \
+	fflush(0); \
+	fprintf(stderr, "[%s] *** error: " fmt ": %s\n", \
+			progname, ## __VA_ARGS__, strerror(save)); \
+} while (0)
+
+#define VERBOSE(fmt, ...) do { \
+	if (verbose) { \
+		fprintf(stdout, "[%s] " fmt "\n", progname, ## __VA_ARGS__); \
+	} \
+} while (0)
+
+#define STAG_SIZE 16
+#define STAG_MAGIC	0x2B24
+#define STAG_ID		0x02
+
+#define CSXF_SIZE 16
+#define CSXF_MAGIC	0x5343
+
+#define MAX_DATA_HEADER 128
+#define DATA_HEADER_UNKNOWN 0x8000
+#define DATA_HEADER_EEPROM 0xF5
+#define DATA_HEADER_CONFIG 0x42
+#define DATA_HEADER_SIZE 6
+
+#define DATA_HEADER_ID_MAC 0x30
+#define DATA_HEADER_ID_CAL 0x0
+
+/* ARM update header 2.0
+ * used only in factory images to erase and flash selected area
+ */
+struct stag_header {		/* used only of sch2 wrapped kernel data */
+	uint8_t cmark;		/* in factory 0xFF ,in sysuograde must be the same as id */
+	uint8_t id;		/* 0x04 */
+	uint16_t magic;		/* magic 0x2B24 */
+	uint32_t time_stamp;	/* timestamp calculated in jboot way */
+	uint32_t image_length;	/* lentgh of kernel + sch2 header */
+	uint16_t image_checksum;	/* negated jboot_checksum of sch2 + kernel */
+	uint16_t tag_checksum;	/* negated jboot_checksum of stag header data */
+};
+
+struct csxf_header {
+	uint16_t magic;		/* 0x5343, 'CS' in little endian */
+	uint16_t checksum;	/* checksum, include header & body */
+	uint32_t body_length;	/* length of body */
+	uint8_t body_encoding;	/* encoding method of body */
+	uint8_t reserved[3];
+	uint32_t raw_length;	/* length of body before encoded */
+};
+
+struct data_header {
+	uint8_t id;
+	uint8_t type;		/* 0x42xx for config 0xF5xx for eeprom */
+	uint16_t unknown;
+	uint16_t length;	/* length of body */
+	uint8_t data[];		/* encoding method of body */
+};
+
+/* globals */
+
+char *ofname;
+char *ifname;
+char *progname;
+
+uint8_t *buffer;
+uint32_t config_size;
+
+uint32_t start_offset;
+uint8_t mac_duplicate;
+uint8_t mac_print;
+uint8_t print_data;
+uint8_t verbose;
+
+static void usage(int status)
+{
+	fprintf(stderr, "Usage: %s [OPTIONS...]\n", progname);
+	fprintf(stderr,
+		"\n"
+		"Options:\n"
+		"  -i <file>       config partition file <file>\n"
+		"  -m              print mac address\n"
+		"  -e <file>       save eeprom calibration data image to the file <file>\n"
+		"  -o <offset>     set start offset to <ofset>\n"
+		"  -p              print config data\n"
+		"  -v              verbose\n"
+		"  -h              show this screen\n");
+
+	exit(status);
+}
+
+static void print_data_header(struct data_header *printed_header)
+{
+	printf("id: 0x%02X "
+	       "type: 0x%02X "
+	       "unknown: 0x%04X "
+	       "length: 0x%04X\n"
+	       "data: ",
+	       printed_header->id,
+	       printed_header->type,
+	       printed_header->unknown, printed_header->length);
+
+	for (uint16_t i = 0; i < printed_header->length; i++)
+		printf("%02X ", printed_header->data[i]);
+
+	printf("\n");
+
+}
+
+static uint16_t jboot_checksum(uint16_t start_val, uint16_t *data, int size)
+{
+	uint32_t counter = start_val;
+	uint16_t *ptr = data;
+
+	while (size > 1) {
+		counter += *ptr;
+		++ptr;
+		while (counter >> 16)
+			counter = (uint16_t) counter + (counter >> 16);
+		size -= 2;
+	}
+	if (size > 0) {
+		counter += *(uint8_t *) ptr;
+		counter -= 0xFF;
+	}
+	while (counter >> 16)
+		counter = (uint16_t) counter + (counter >> 16);
+	return counter;
+}
+
+static int find_header(uint8_t *buf, uint32_t buf_size,
+		       struct data_header **data_table)
+{
+	uint8_t *tmp_buf = buf + start_offset;
+	uint8_t tmp_hdr[4] = { STAG_ID, STAG_ID, (STAG_MAGIC & 0xFF), (STAG_MAGIC >> 8) };
+	struct csxf_header *tmp_csxf_header;
+	uint16_t tmp_checksum = 0;
+	uint16_t data_header_counter = 0;
+	int ret = EXIT_FAILURE;
+
+	VERBOSE("Looking for STAG header!");
+
+	while ((uint32_t) tmp_buf - (uint32_t) buf <= buf_size) {
+		if (!memcmp(tmp_buf, tmp_hdr, 4)) {
+			if (((struct stag_header *)tmp_buf)->tag_checksum ==
+			    (uint16_t) ~jboot_checksum(0, (uint16_t *) tmp_buf,
+							STAG_SIZE - 2)) {
+				VERBOSE("Found proper STAG header at: 0x%X.",
+					tmp_buf - buf);
+				break;
+			}
+		}
+		tmp_buf++;
+	}
+
+	tmp_csxf_header = (struct csxf_header *)(tmp_buf + STAG_SIZE);
+	if (tmp_csxf_header->magic != CSXF_MAGIC) {
+		ERR("CSXF magic incorrect! 0x%X != 0x%X",
+		    tmp_csxf_header->magic, CSXF_MAGIC);
+		goto out;
+	}
+	VERBOSE("CSXF magic ok.");
+	tmp_checksum = tmp_csxf_header->checksum;
+	tmp_csxf_header->checksum = 0;
+
+	tmp_csxf_header->checksum =
+	    (uint16_t) ~jboot_checksum(0, (uint16_t *) (tmp_buf + STAG_SIZE),
+					tmp_csxf_header->raw_length +
+					CSXF_SIZE);
+
+	if (tmp_checksum != tmp_csxf_header->checksum) {
+		ERR("CSXF checksum incorrect! Stored: 0x%X Calculated: 0x%X",
+		    tmp_checksum, tmp_csxf_header->checksum);
+		goto out;
+	}
+	VERBOSE("CSXF image checksum ok.");
+
+	tmp_buf = tmp_buf + STAG_SIZE + CSXF_SIZE;
+
+	while ((uint32_t) tmp_buf - (uint32_t) buf <= buf_size) {
+
+		struct data_header *tmp_data_header =
+		    (struct data_header *)tmp_buf;
+
+		if (tmp_data_header->unknown != DATA_HEADER_UNKNOWN) {
+			tmp_buf++;
+			continue;
+		}
+		if (tmp_data_header->type != DATA_HEADER_EEPROM
+		    && tmp_data_header->type != DATA_HEADER_CONFIG) {
+			tmp_buf++;
+			continue;
+		}
+
+		data_table[data_header_counter] = tmp_data_header;
+		tmp_buf +=
+		    DATA_HEADER_SIZE + data_table[data_header_counter]->length;
+		data_header_counter++;
+
+	}
+
+	ret = data_header_counter;
+
+ out:
+	return ret;
+}
+
+static int read_file(char *file_name)
+{
+	int ret = EXIT_FAILURE;
+	uint32_t file_size = 0;
+	FILE *fp;
+
+	fp = fopen(file_name, "r");
+
+	if (!fp) {
+		ERR("Failed to open config input file %s", file_name);
+		goto out;
+	}
+
+	fseek(fp, 0L, SEEK_END);
+	file_size = ftell(fp);
+	fseek(fp, 0L, SEEK_SET);
+
+	buffer = malloc(file_size);
+	VERBOSE("Allocated %d bytes.", file_size);
+
+	if (fread(buffer, 1, file_size, fp) != file_size) {
+		ERR("Failed to read config input file %s", file_name);
+		goto out_free_buf;
+	}
+
+	VERBOSE("Read %d bytes of config input file %s", file_size, file_name);
+	config_size = file_size;
+	ret = EXIT_SUCCESS;
+	goto out;
+
+ out_free_buf:
+	free(buffer);
+	fclose(fp);
+ out:
+	return ret;
+}
+
+static int write_file(const char *ofname, const uint8_t *data, int len)
+{
+	FILE *f;
+	int ret = EXIT_FAILURE;
+
+	f = fopen(ofname, "w");
+	if (f == NULL) {
+		ERRS("could not open \"%s\" for writing", ofname);
+		goto out;
+	}
+
+	errno = 0;
+	fwrite(data, len, 1, f);
+	if (errno) {
+		ERRS("unable to write output file");
+		goto out_flush;
+	}
+
+	VERBOSE("firmware file \"%s\" completed", ofname);
+
+	ret = EXIT_SUCCESS;
+
+ out_flush:
+	fflush(f);
+	fclose(f);
+	if (ret != EXIT_SUCCESS)
+		unlink(ofname);
+ out:
+	return ret;
+}
+
+static void print_mac(struct data_header **data_table, int cnt)
+{
+
+	for (int i = 0; i < cnt; i++) {
+		if (data_table[i]->type == DATA_HEADER_CONFIG
+		    && data_table[i]->id == DATA_HEADER_ID_MAC) {
+			int j;
+			for (j = 0; j < 5; j++)
+				printf("%02x:", data_table[i]->data[j]);
+			printf("%02x\n", data_table[i]->data[j]);
+		}
+
+	}
+
+}
+
+static int write_eeprom(struct data_header **data_table, int cnt)
+{
+	int ret = EXIT_FAILURE;
+
+	for (int i = 0; i < cnt; i++) {
+		if (data_table[i]->type == DATA_HEADER_EEPROM
+		    && data_table[i]->id == DATA_HEADER_ID_CAL) {
+			ret =
+			    write_file(ofname, data_table[i]->data,
+				       data_table[i]->length);
+			break;
+		}
+
+	}
+
+	return ret;
+}
+
+int main(int argc, char *argv[])
+{
+	int ret = EXIT_FAILURE;
+	int configs_counter = 0;
+	struct data_header *configs_table[MAX_DATA_HEADER];
+	buffer = NULL;
+	config_size = 0;
+
+	progname = basename(argv[0]);
+	start_offset = 0;
+	mac_print = 0;
+	print_data = 0;
+	verbose = 0;
+	ofname = NULL;
+	ifname = NULL;
+
+	while (1) {
+		int c;
+
+		c = getopt(argc, argv, "de:hi:mo:pv");
+		if (c == -1)
+			break;
+
+		switch (c) {
+		case 'm':
+			mac_print = 1;
+			break;
+		case 'i':
+			ifname = optarg;
+			break;
+		case 'e':
+			ofname = optarg;
+			break;
+		case 'o':
+			sscanf(optarg, "0x%x", &start_offset);
+			break;
+		case 'p':
+			print_data = 1;
+			break;
+		case 'v':
+			verbose = 1;
+			VERBOSE("Enable verbose!");
+			break;
+		default:
+			usage(EXIT_FAILURE);
+			break;
+		}
+	}
+
+	if (!ifname)
+		usage(EXIT_FAILURE);
+
+	ret = read_file(ifname);
+
+	if (ret || config_size <= 0)
+		goto out;
+
+	configs_counter = find_header(buffer, config_size, configs_table);
+
+	if (configs_counter <= 0)
+		goto out_free_buf;
+
+	if (print_data || verbose) {
+		for (int i = 0; i < configs_counter; i++)
+			print_data_header(configs_table[i]);
+	}
+
+	if (mac_print)
+		print_mac(configs_table, configs_counter);
+
+	ret = EXIT_SUCCESS;
+
+	if (ofname)
+		ret = write_eeprom(configs_table, configs_counter);
+
+ out_free_buf:
+	free(buffer);
+ out:
+	return ret;
+
+}
diff --git a/package/utils/jsonfilter/Makefile b/package/utils/jsonfilter/Makefile
new file mode 100644
index 0000000..d243ac7
--- /dev/null
+++ b/package/utils/jsonfilter/Makefile
@@ -0,0 +1,32 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=jsonfilter
+PKG_RELEASE:=1
+
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_URL=$(PROJECT_GIT)/project/jsonpath.git
+PKG_SOURCE_DATE:=2024-01-23
+PKG_SOURCE_VERSION:=594cfa86469c005972ba750614f5b3f1af84d0f6
+PKG_MIRROR_HASH:=92bb2bc64be6769bd16c2c3c0e955e8f58abd6b99ffe6841d089e08df78fc8b7
+CMAKE_INSTALL:=1
+
+PKG_MAINTAINER:=Jo-Philipp Wich <jo@mein.io>
+PKG_LICENSE:=ISC
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/cmake.mk
+
+define Package/jsonfilter
+  SECTION:=base
+  CATEGORY:=Base system
+  DEPENDS:=+libubox +libjson-c
+  TITLE:=OpenWrt JSON filter utility
+  URL:=$(PKG_SOURCE_URL)
+endef
+
+define Package/jsonfilter/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/jsonpath $(1)/usr/bin/jsonfilter
+endef
+
+$(eval $(call BuildPackage,jsonfilter))
diff --git a/package/utils/kmod/Makefile b/package/utils/kmod/Makefile
new file mode 100644
index 0000000..3abd289
--- /dev/null
+++ b/package/utils/kmod/Makefile
@@ -0,0 +1,92 @@
+#
+# Copyright (C) 2015 Jeff Waugh
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=kmod
+PKG_VERSION:=32
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=@KERNEL/linux/utils/kernel/kmod
+PKG_HASH:=630ed0d92275a88cb9a7bf68f5700e911fdadaf02e051cf2e4680ff8480bd492
+
+PKG_MAINTAINER:=Jeff Waugh <jdub@bethesignal.org>
+PKG_LICENSE:=LGPL-2.1-or-later
+PKG_LICENSE_FILES:=COPYING
+PKG_CPE_ID:=cpe:/a:kernel:kmod
+
+PKG_FIXUP:=autoreconf
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+CONFIGURE_ARGS += --with-zlib
+
+define Package/kmod/Default
+  SECTION:=utils
+  CATEGORY:=Utilities
+  TITLE:=Linux kernel module handling
+  URL:=https://www.kernel.org/pub/linux/utils/kernel/kmod/
+  DEPENDS:=+zlib
+endef
+
+
+define Package/kmod
+$(call Package/kmod/Default)
+  TITLE+= (tools)
+  ALTERNATIVES:=\
+    200:/sbin/depmod:/sbin/kmod \
+    200:/sbin/insmod:/sbin/kmod \
+    200:/sbin/lsmod:/sbin/kmod \
+    200:/sbin/modinfo:/sbin/kmod \
+    200:/sbin/modprobe:/sbin/kmod \
+    200:/sbin/rmmod:/sbin/kmod
+endef
+
+define Package/kmod/description
+Linux kernel module handling
+ kmod is a set of tools to handle common tasks with Linux kernel modules like
+ insert, remove, list, check properties, resolve dependencies and aliases.
+endef
+
+define Package/kmod/install
+	$(INSTALL_DIR) $(1)/sbin
+	$(CP) $(PKG_INSTALL_DIR)/usr/bin/kmod $(1)/sbin
+endef
+
+
+define Package/libkmod
+$(call Package/kmod/Default)
+  SECTION:=libs
+  CATEGORY:=Libraries
+  TITLE+= (library)
+endef
+
+define Package/libkmod/install
+	$(INSTALL_DIR) $(1)/usr/lib
+	$(CP) $(PKG_INSTALL_DIR)/usr/lib/libkmod.so.* $(1)/usr/lib/
+endef
+
+
+define Build/InstallDev
+	$(INSTALL_DIR) $(1)/usr/include
+	$(CP) $(PKG_INSTALL_DIR)/usr/include $(1)/usr/
+
+	$(INSTALL_DIR) $(1)/usr/lib
+	$(CP) $(PKG_INSTALL_DIR)/usr/lib/libkmod.{so*,la} $(1)/usr/lib/
+
+	$(INSTALL_DIR) $(1)/usr/lib/pkgconfig
+	$(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/libkmod.pc $(1)/usr/lib/pkgconfig/
+	$(SED) 's,/usr/include,$$$${prefix}/include,g' $(1)/usr/lib/pkgconfig/libkmod.pc
+	$(SED) 's,/usr/lib,$$$${exec_prefix}/lib,g' $(1)/usr/lib/pkgconfig/libkmod.pc
+endef
+
+
+$(eval $(call BuildPackage,kmod))
+$(eval $(call BuildPackage,libkmod))
diff --git a/package/utils/kmod/patches/010-basename.patch b/package/utils/kmod/patches/010-basename.patch
new file mode 100644
index 0000000..0c04685
--- /dev/null
+++ b/package/utils/kmod/patches/010-basename.patch
@@ -0,0 +1,91 @@
+--- a/libkmod/libkmod-config.c
++++ b/libkmod/libkmod-config.c
+@@ -21,6 +21,7 @@
+ #include <ctype.h>
+ #include <dirent.h>
+ #include <errno.h>
++#include <libgen.h>
+ #include <stdarg.h>
+ #include <stddef.h>
+ #include <stdio.h>
+@@ -794,7 +795,9 @@ static int conf_files_insert_sorted(stru
+ 	bool is_single = false;
+ 
+ 	if (name == NULL) {
+-		name = basename(path);
++		char *pathc = strdup(path);
++		name = basename(pathc);
++		free(pathc);
+ 		is_single = true;
+ 	}
+ 
+--- a/shared/util.c
++++ b/shared/util.c
+@@ -22,6 +22,7 @@
+ #include <assert.h>
+ #include <ctype.h>
+ #include <errno.h>
++#include <libgen.h>
+ #include <stdarg.h>
+ #include <stddef.h>
+ #include <stdio.h>
+@@ -173,8 +174,10 @@ char *modname_normalize(const char *modn
+ char *path_to_modname(const char *path, char buf[static PATH_MAX], size_t *len)
+ {
+ 	char *modname;
++	char *pathc = strdup(path);
+ 
+-	modname = basename(path);
++	modname = basename(pathc);
++	free(pathc);
+ 	if (modname == NULL || modname[0] == '\0')
+ 		return NULL;
+ 
+--- a/tools/depmod.c
++++ b/tools/depmod.c
+@@ -22,6 +22,7 @@
+ #include <dirent.h>
+ #include <errno.h>
+ #include <getopt.h>
++#include <libgen.h>
+ #include <limits.h>
+ #include <regex.h>
+ #include <stdio.h>
+@@ -757,14 +758,17 @@ static int cfg_files_insert_sorted(struc
+ 	struct cfg_file **files, *f;
+ 	size_t i, n_files, namelen, dirlen;
+ 	void *tmp;
++	char *dirc;
+ 
+ 	dirlen = strlen(dir);
+ 	if (name != NULL)
+ 		namelen = strlen(name);
+ 	else {
+-		name = basename(dir);
++		dirc = strdup(dir);
++		name = basename(dirc);
+ 		namelen = strlen(name);
+ 		dirlen -= namelen + 1;
++		free(dirc);
+ 	}
+ 
+ 	n_files = *p_n_files;
+@@ -2613,7 +2617,7 @@ static int depmod_output(struct depmod *
+ 			int mode = 0644;
+ 			int fd;
+ 
+-			snprintf(tmp, sizeof(tmp), "%s.%i.%li.%li", itr->name, getpid(),
++			snprintf(tmp, sizeof(tmp), "%s.%i.%" PRId64 ".%" PRId64, itr->name, getpid(),
+ 					tv.tv_usec, tv.tv_sec);
+ 			fd = openat(dfd, tmp, flags, mode);
+ 			if (fd < 0) {
+--- a/tools/kmod.c
++++ b/tools/kmod.c
+@@ -22,6 +22,7 @@
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
++#include <libgen.h>
+ 
+ #include <shared/util.h>
+ 
diff --git a/package/utils/lua/Makefile b/package/utils/lua/Makefile
new file mode 100644
index 0000000..36d332f
--- /dev/null
+++ b/package/utils/lua/Makefile
@@ -0,0 +1,189 @@
+#
+# Copyright (C) 2006-2014 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=lua
+PKG_VERSION:=5.1.5
+PKG_RELEASE:=11
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://www.lua.org/ftp/ \
+	https://www.tecgraf.puc-rio.br/lua/ftp/
+PKG_HASH:=2640fc56a795f29d28ef15e13c34a47e223960b0240e8cb0a82d9b0738695333
+PKG_BUILD_PARALLEL:=1
+
+PKG_LICENSE:=MIT
+PKG_LICENSE_FILES:=COPYRIGHT
+PKG_CPE_ID:=cpe:/a:lua:lua
+
+PKG_BUILD_FLAGS:=no-lto
+
+HOST_PATCH_DIR := ./patches-host
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/host-build.mk
+
+define Package/lua/Default
+  SUBMENU:=Lua
+  SECTION:=lang
+  CATEGORY:=Languages
+  TITLE:=Lua programming language
+  URL:=https://www.lua.org/
+  MAINTAINER:=Jo-Philipp Wich <jo@mein.io>
+endef
+
+define Package/lua/Default/description
+ Lua is a powerful light-weight programming language designed for extending 
+ applications. Lua is also frequently used as a general-purpose, stand-alone 
+ language. Lua is free software.
+endef
+
+define Package/liblua
+$(call Package/lua/Default)
+  SUBMENU:=
+  SECTION:=libs
+  CATEGORY:=Libraries
+  TITLE+= (libraries)
+  ABI_VERSION:=5.1.5
+endef
+
+define Package/liblua/description
+$(call Package/lua/Default/description)
+ This package contains the Lua shared libraries, needed by other programs.
+endef
+
+define Package/lua
+$(call Package/lua/Default)
+  DEPENDS:=+liblua
+  TITLE+= (interpreter)
+endef
+
+define Package/lua/description
+$(call Package/lua/Default/description)
+ This package contains the Lua language interpreter.
+endef
+
+define Package/luac
+$(call Package/lua/Default)
+  DEPENDS:=+liblua
+  TITLE+= (compiler)
+endef
+
+define Package/luac/description
+$(call Package/lua/Default/description)
+ This package contains the Lua language compiler.
+endef
+
+define Package/lua-examples
+$(call Package/lua/Default)
+  DEPENDS:=lua
+  TITLE+= (examples)
+endef
+
+define Package/lua-examples/description
+$(call Package/lua/Default/description)
+ This package contains Lua language examples.
+endef
+
+define Build/Configure
+endef
+
+TARGET_CFLAGS += -DLUA_USE_LINUX $(FPIC) -std=gnu99
+
+define Build/Compile
+	$(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR) \
+		CC="$(TARGET_CROSS)gcc" \
+		AR="$(TARGET_CROSS)ar rcu" \
+		RANLIB="$(TARGET_CROSS)ranlib" \
+		INSTALL_ROOT=/usr \
+		CFLAGS="$(TARGET_CPPFLAGS) $(TARGET_CFLAGS)" \
+		MYLDFLAGS="$(TARGET_LDFLAGS)" \
+		PKG_VERSION=$(PKG_VERSION) \
+		linux
+	rm -rf $(PKG_INSTALL_DIR)
+	mkdir -p $(PKG_INSTALL_DIR)
+	$(MAKE) -C $(PKG_BUILD_DIR) \
+		INSTALL_TOP="$(PKG_INSTALL_DIR)/usr" \
+		install
+endef
+
+define Host/Configure
+	$(SED) 's,"/usr/local/","$(STAGING_DIR_HOSTPKG)/",' $(HOST_BUILD_DIR)/src/luaconf.h
+endef
+
+ifeq ($(HOST_OS),Darwin)
+	LUA_OS:=macosx
+else
+	ifeq ($(HOST_OS),FreeBSD)
+		LUA_OS:=freebsd
+	else
+		LUA_OS:=linux
+	endif
+endif
+
+define Host/Compile
+	$(MAKE) -C $(HOST_BUILD_DIR) \
+		CC="$(HOSTCC) $(HOST_FPIC) -std=gnu99" \
+		$(LUA_OS)
+endef
+
+define Host/Install
+	$(MAKE) -C $(HOST_BUILD_DIR) \
+		INSTALL_TOP="$(STAGING_DIR_HOSTPKG)" \
+		install
+
+	$(INSTALL_DIR) $(STAGING_DIR_HOSTPKG)/lib/pkgconfig
+	$(CP) $(HOST_BUILD_DIR)/etc/lua.pc $(STAGING_DIR_HOSTPKG)/lib/pkgconfig/lua5.1.pc
+
+	$(LN) lua5.1 $(STAGING_DIR_HOSTPKG)/bin/lua
+	$(LN) luac5.1 $(STAGING_DIR_HOSTPKG)/bin/luac
+	$(LN) lua5.1.pc $(STAGING_DIR_HOSTPKG)/lib/pkgconfig/lua.pc
+endef
+
+define Build/InstallDev
+	$(INSTALL_DIR) $(1)/usr/include
+	$(CP) $(PKG_INSTALL_DIR)/usr/include/lua{,lib,conf}.h $(1)/usr/include/
+	$(CP) $(PKG_INSTALL_DIR)/usr/include/lua.hpp $(1)/usr/include/
+	$(CP) $(PKG_INSTALL_DIR)/usr/include/lauxlib.h $(1)/usr/include/
+	$(CP) $(PKG_INSTALL_DIR)/usr/include/lnum_config.h $(1)/usr/include/
+	$(INSTALL_DIR) $(1)/usr/lib
+	$(CP) $(PKG_INSTALL_DIR)/usr/lib/liblua.{a,so*} $(1)/usr/lib/
+	$(LN) liblua.so.$(PKG_VERSION) $(1)/usr/lib/liblualib.so
+	$(INSTALL_DIR) $(1)/usr/lib/pkgconfig
+	$(CP) $(PKG_BUILD_DIR)/etc/lua.pc $(1)/usr/lib/pkgconfig/
+endef
+
+define Package/liblua/install
+	$(INSTALL_DIR) $(1)/usr/lib
+	$(CP) $(PKG_INSTALL_DIR)/usr/lib/liblua.so.* $(1)/usr/lib/
+endef
+
+define Package/lua/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/lua5.1 $(1)/usr/bin/
+	$(LN) lua5.1 $(1)/usr/bin/lua
+endef
+
+define Package/luac/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/luac5.1 $(1)/usr/bin/
+	$(LN) luac5.1 $(1)/usr/bin/luac
+endef
+
+define Package/lua-examples/install
+	$(INSTALL_DIR) $(1)/usr/share/lua/examples
+	$(INSTALL_DATA) $(PKG_BUILD_DIR)/test/*.lua \
+		$(1)/usr/share/lua/examples/
+endef
+
+$(eval $(call BuildPackage,liblua))
+$(eval $(call BuildPackage,lua))
+$(eval $(call BuildPackage,luac))
+$(eval $(call BuildPackage,lua-examples))
+$(eval $(call HostBuild))
+
diff --git a/package/utils/lua/patches-host/001-include-version-number.patch b/package/utils/lua/patches-host/001-include-version-number.patch
new file mode 100644
index 0000000..806d370
--- /dev/null
+++ b/package/utils/lua/patches-host/001-include-version-number.patch
@@ -0,0 +1,56 @@
+From 96576b44a1b368bd6590eb0778ae45cc9ccede3f Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
+Date: Fri, 21 Jun 2019 14:08:38 +0200
+Subject: [PATCH] include version number
+
+Including it allows multiple lua versions to coexist.
+
+Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
+---
+
+--- a/Makefile
++++ b/Makefile
+@@ -41,10 +41,10 @@ RANLIB= ranlib
+ PLATS= aix ansi bsd freebsd generic linux macosx mingw posix solaris
+ 
+ # What to install.
+-TO_BIN= lua luac
++TO_BIN= lua$V luac$V
+ TO_INC= lua.h luaconf.h lualib.h lauxlib.h ../etc/lua.hpp
+ TO_LIB= liblua.a
+-TO_MAN= lua.1 luac.1
++TO_MAN= lua$V.1 luac$V.1
+ 
+ # Lua version and release.
+ V= 5.1
+@@ -53,7 +53,7 @@ R= 5.1.5
+ all:	$(PLAT)
+ 
+ $(PLATS) clean:
+-	cd src && $(MAKE) $@
++	cd src && $(MAKE) $@ V=$V
+ 
+ test:	dummy
+ 	src/lua test/hello.lua
+diff --git a/doc/lua.1 b/doc/lua5.1.1
+rename from doc/lua.1
+rename to doc/lua5.1.1
+diff --git a/doc/luac.1 b/doc/luac5.1.1
+rename from doc/luac.1
+rename to doc/luac5.1.1
+diff --git a/src/Makefile b/src/Makefile
+--- a/src/Makefile
++++ b/src/Makefile
+@@ -29,10 +29,10 @@ CORE_O=	lapi.o lcode.o ldebug.o ldo.o ld
+ LIB_O=	lauxlib.o lbaselib.o ldblib.o liolib.o lmathlib.o loslib.o ltablib.o \
+ 	lstrlib.o loadlib.o linit.o
+ 
+-LUA_T=	lua
++LUA_T=	lua$V
+ LUA_O=	lua.o
+ 
+-LUAC_T=	luac
++LUAC_T=	luac$V
+ LUAC_O=	luac.o print.o
+ 
+ ALL_O= $(CORE_O) $(LIB_O) $(LUA_O) $(LUAC_O)
diff --git a/package/utils/lua/patches-host/010-lua-5.1.3-lnum-full-260308.patch b/package/utils/lua/patches-host/010-lua-5.1.3-lnum-full-260308.patch
new file mode 100644
index 0000000..fd398c2
--- /dev/null
+++ b/package/utils/lua/patches-host/010-lua-5.1.3-lnum-full-260308.patch
@@ -0,0 +1,3748 @@
+--- a/Makefile
++++ b/Makefile
+@@ -42,7 +42,7 @@ PLATS= aix ansi bsd freebsd generic linu
+ 
+ # What to install.
+ TO_BIN= lua$V luac$V
+-TO_INC= lua.h luaconf.h lualib.h lauxlib.h ../etc/lua.hpp
++TO_INC= lua.h luaconf.h lualib.h lauxlib.h lnum_config.h ../etc/lua.hpp
+ TO_LIB= liblua.a
+ TO_MAN= lua$V.1 luac$V.1
+ 
+--- a/src/Makefile
++++ b/src/Makefile
+@@ -25,7 +25,7 @@ PLATS= aix ansi bsd freebsd generic linu
+ LUA_A=	liblua.a
+ CORE_O=	lapi.o lcode.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o lmem.o \
+ 	lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o ltm.o  \
+-	lundump.o lvm.o lzio.o
++	lundump.o lvm.o lzio.o lnum.o
+ LIB_O=	lauxlib.o lbaselib.o ldblib.o liolib.o lmathlib.o loslib.o ltablib.o \
+ 	lstrlib.o loadlib.o linit.o
+ 
+@@ -148,6 +148,7 @@ llex.o: llex.c lua.h luaconf.h ldo.h lob
+ lmathlib.o: lmathlib.c lua.h luaconf.h lauxlib.h lualib.h
+ lmem.o: lmem.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \
+   ltm.h lzio.h lmem.h ldo.h
++lnum.o: lnum.c lua.h llex.h lnum.h
+ loadlib.o: loadlib.c lua.h luaconf.h lauxlib.h lualib.h
+ lobject.o: lobject.c lua.h luaconf.h ldo.h lobject.h llimits.h lstate.h \
+   ltm.h lzio.h lmem.h lstring.h lgc.h lvm.h
+@@ -179,4 +180,18 @@ lzio.o: lzio.c lua.h luaconf.h llimits.h
+ print.o: print.c ldebug.h lstate.h lua.h luaconf.h lobject.h llimits.h \
+   ltm.h lzio.h lmem.h lopcodes.h lundump.h
+ 
++luaconf.h: lnum_config.h
++lapi.c: lnum.h
++lauxlib.c: llimits.h
++lbaselib.c: llimits.h lobject.h lapi.h
++lcode.c: lnum.h
++liolib.c: lnum.h llex.h
++llex.c: lnum.h
++lnum.h: lobject.h
++lobject.c: llex.h lnum.h
++ltable.c: lnum.h
++lua.c: llimits.h
++lvm.c: llex.h lnum.h
++print.c: lnum.h
++
+ # (end of Makefile)
+--- a/src/lapi.c
++++ b/src/lapi.c
+@@ -28,7 +28,7 @@
+ #include "ltm.h"
+ #include "lundump.h"
+ #include "lvm.h"
+-
++#include "lnum.h"
+ 
+ 
+ const char lua_ident[] =
+@@ -241,12 +241,13 @@ LUA_API void lua_pushvalue (lua_State *L
+ 
+ LUA_API int lua_type (lua_State *L, int idx) {
+   StkId o = index2adr(L, idx);
+-  return (o == luaO_nilobject) ? LUA_TNONE : ttype(o);
++  return (o == luaO_nilobject) ? LUA_TNONE : ttype_ext(o);
+ }
+ 
+ 
+ LUA_API const char *lua_typename (lua_State *L, int t) {
+   UNUSED(L);
++  lua_assert( t!= LUA_TINT );
+   return (t == LUA_TNONE) ? "no value" : luaT_typenames[t];
+ }
+ 
+@@ -264,6 +265,14 @@ LUA_API int lua_isnumber (lua_State *L,
+ }
+ 
+ 
++LUA_API int lua_isinteger (lua_State *L, int idx) {
++  TValue tmp;
++  lua_Integer dum;
++  const TValue *o = index2adr(L, idx);
++  return tonumber(o,&tmp) && (ttisint(o) || tt_integer_valued(o,&dum));
++}
++
++
+ LUA_API int lua_isstring (lua_State *L, int idx) {
+   int t = lua_type(L, idx);
+   return (t == LUA_TSTRING || t == LUA_TNUMBER);
+@@ -309,31 +318,66 @@ LUA_API int lua_lessthan (lua_State *L,
+ }
+ 
+ 
+-
+ LUA_API lua_Number lua_tonumber (lua_State *L, int idx) {
+   TValue n;
+   const TValue *o = index2adr(L, idx);
+-  if (tonumber(o, &n))
++  if (tonumber(o, &n)) {
++#ifdef LNUM_COMPLEX
++    if (nvalue_img(o) != 0)
++      luaG_runerror(L, "expecting a real number");
++#endif
+     return nvalue(o);
+-  else
+-    return 0;
++  }
++  return 0;
+ }
+ 
+ 
+ LUA_API lua_Integer lua_tointeger (lua_State *L, int idx) {
+   TValue n;
++    /* Lua 5.1 documented behaviour is to return nonzero for non-integer:
++     * "If the number is not an integer, it is truncated in some non-specified way." 
++     * I would suggest to change this, to return 0 for anything that would
++     * not fit in 'lua_Integer'.
++     */
++#ifdef LUA_COMPAT_TOINTEGER
++  /* Lua 5.1 compatible */
+   const TValue *o = index2adr(L, idx);
+   if (tonumber(o, &n)) {
+-    lua_Integer res;
+-    lua_Number num = nvalue(o);
+-    lua_number2integer(res, num);
+-    return res;
++    lua_Integer i;
++    lua_Number d;
++    if (ttisint(o)) return ivalue(o);
++    d= nvalue_fast(o);
++# ifdef LNUM_COMPLEX
++    if (nvalue_img_fast(o) != 0)
++      luaG_runerror(L, "expecting a real number");
++# endif
++    lua_number2integer(i, d);
++    return i;
+   }
+-  else
+-    return 0;
++#else
++  /* New suggestion */
++  const TValue *o = index2adr(L, idx);
++  if (tonumber(o, &n)) {
++    lua_Integer i;
++    if (ttisint(o)) return ivalue(o);
++    if (tt_integer_valued(o,&i)) return i;
++  }
++#endif
++  return 0;
+ }
+ 
+ 
++#ifdef LNUM_COMPLEX
++LUA_API lua_Complex lua_tocomplex (lua_State *L, int idx) {
++  TValue tmp;
++  const TValue *o = index2adr(L, idx);
++  if (tonumber(o, &tmp))
++    return nvalue_complex(o);
++  return 0;
++}
++#endif
++
++
+ LUA_API int lua_toboolean (lua_State *L, int idx) {
+   const TValue *o = index2adr(L, idx);
+   return !l_isfalse(o);
+@@ -364,6 +408,7 @@ LUA_API size_t lua_objlen (lua_State *L,
+     case LUA_TSTRING: return tsvalue(o)->len;
+     case LUA_TUSERDATA: return uvalue(o)->len;
+     case LUA_TTABLE: return luaH_getn(hvalue(o));
++    case LUA_TINT:
+     case LUA_TNUMBER: {
+       size_t l;
+       lua_lock(L);  /* `luaV_tostring' may create a new string */
+@@ -426,6 +471,8 @@ LUA_API void lua_pushnil (lua_State *L)
+ }
+ 
+ 
++/* 'lua_pushnumber()' may lose accuracy on integers, 'lua_pushinteger' will not.
++ */
+ LUA_API void lua_pushnumber (lua_State *L, lua_Number n) {
+   lua_lock(L);
+   setnvalue(L->top, n);
+@@ -434,12 +481,22 @@ LUA_API void lua_pushnumber (lua_State *
+ }
+ 
+ 
+-LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) {
++LUA_API void lua_pushinteger (lua_State *L, lua_Integer i) {
++  lua_lock(L);
++  setivalue(L->top, i);
++  api_incr_top(L);
++  lua_unlock(L);
++}
++
++
++#ifdef LNUM_COMPLEX
++LUA_API void lua_pushcomplex (lua_State *L, lua_Complex v) {
+   lua_lock(L);
+-  setnvalue(L->top, cast_num(n));
++  setnvalue_complex( L->top, v );
+   api_incr_top(L);
+   lua_unlock(L);
+ }
++#endif
+ 
+ 
+ LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len) {
+@@ -569,7 +626,7 @@ LUA_API void lua_rawgeti (lua_State *L,
+   lua_lock(L);
+   o = index2adr(L, idx);
+   api_check(L, ttistable(o));
+-  setobj2s(L, L->top, luaH_getnum(hvalue(o), n));
++  setobj2s(L, L->top, luaH_getint(hvalue(o), n));
+   api_incr_top(L);
+   lua_unlock(L);
+ }
+@@ -597,6 +654,9 @@ LUA_API int lua_getmetatable (lua_State
+     case LUA_TUSERDATA:
+       mt = uvalue(obj)->metatable;
+       break;
++    case LUA_TINT:
++      mt = G(L)->mt[LUA_TNUMBER];
++      break;
+     default:
+       mt = G(L)->mt[ttype(obj)];
+       break;
+@@ -687,7 +747,7 @@ LUA_API void lua_rawseti (lua_State *L,
+   api_checknelems(L, 1);
+   o = index2adr(L, idx);
+   api_check(L, ttistable(o));
+-  setobj2t(L, luaH_setnum(L, hvalue(o), n), L->top-1);
++  setobj2t(L, luaH_setint(L, hvalue(o), n), L->top-1);
+   luaC_barriert(L, hvalue(o), L->top-1);
+   L->top--;
+   lua_unlock(L);
+@@ -721,7 +781,7 @@ LUA_API int lua_setmetatable (lua_State
+       break;
+     }
+     default: {
+-      G(L)->mt[ttype(obj)] = mt;
++      G(L)->mt[ttype_ext(obj)] = mt;
+       break;
+     }
+   }
+@@ -1085,3 +1145,32 @@ LUA_API const char *lua_setupvalue (lua_
+   return name;
+ }
+ 
++
++/* Help function for 'luaB_tonumber()', avoids multiple str->number
++ * conversions for Lua "tonumber()".
++ *
++ * Also pushes floating point numbers with integer value as integer, which
++ * can be used by 'tonumber()' in scripts to bring values back to integer
++ * realm.
++ *
++ * Note: The 'back to integer realm' is _not_ to affect string conversions:
++ * 'tonumber("4294967295.1")' should give a floating point value, although
++ * the value would be 4294967296 (and storable in int64 realm).
++ */
++int lua_pushvalue_as_number (lua_State *L, int idx)
++{
++  const TValue *o = index2adr(L, idx);
++  TValue tmp;
++  lua_Integer i;
++  if (ttisnumber(o)) {
++    if ( (!ttisint(o)) && tt_integer_valued(o,&i)) {
++      lua_pushinteger( L, i );
++      return 1;
++    }
++  } else if (!tonumber(o, &tmp)) {
++    return 0;
++  }
++  if (ttisint(o)) lua_pushinteger( L, ivalue(o) );
++  else lua_pushnumber( L, nvalue_fast(o) );
++  return 1;
++}
+--- a/src/lapi.h
++++ b/src/lapi.h
+@@ -13,4 +13,6 @@
+ 
+ LUAI_FUNC void luaA_pushobject (lua_State *L, const TValue *o);
+ 
++int lua_pushvalue_as_number (lua_State *L, int idx);
++
+ #endif
+--- a/src/lauxlib.c
++++ b/src/lauxlib.c
+@@ -23,7 +23,7 @@
+ #include "lua.h"
+ 
+ #include "lauxlib.h"
+-
++#include "llimits.h"
+ 
+ #define FREELIST_REF	0	/* free list of references */
+ 
+@@ -66,7 +66,7 @@ LUALIB_API int luaL_typerror (lua_State
+ 
+ 
+ static void tag_error (lua_State *L, int narg, int tag) {
+-  luaL_typerror(L, narg, lua_typename(L, tag));
++  luaL_typerror(L, narg, tag==LUA_TINT ? "integer" : lua_typename(L, tag));
+ }
+ 
+ 
+@@ -188,8 +188,8 @@ LUALIB_API lua_Number luaL_optnumber (lu
+ 
+ LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int narg) {
+   lua_Integer d = lua_tointeger(L, narg);
+-  if (d == 0 && !lua_isnumber(L, narg))  /* avoid extra test when d is not 0 */
+-    tag_error(L, narg, LUA_TNUMBER);
++  if (d == 0 && !lua_isinteger(L, narg))  /* avoid extra test when d is not 0 */
++    tag_error(L, narg, LUA_TINT);
+   return d;
+ }
+ 
+@@ -200,6 +200,16 @@ LUALIB_API lua_Integer luaL_optinteger (
+ }
+ 
+ 
++#ifdef LNUM_COMPLEX
++LUALIB_API lua_Complex luaL_checkcomplex (lua_State *L, int narg) {
++  lua_Complex c = lua_tocomplex(L, narg);
++  if (c == 0 && !lua_isnumber(L, narg))  /* avoid extra test when c is not 0 */
++    tag_error(L, narg, LUA_TNUMBER);
++  return c;
++}
++#endif
++
++
+ LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) {
+   if (!lua_getmetatable(L, obj))  /* no metatable? */
+     return 0;
+--- a/src/lauxlib.h
++++ b/src/lauxlib.h
+@@ -57,6 +57,12 @@ LUALIB_API lua_Number (luaL_optnumber) (
+ LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int numArg);
+ LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg,
+                                           lua_Integer def);
++#define luaL_checkint32(L,narg) ((int)luaL_checkinteger(L,narg))
++#define luaL_optint32(L,narg,def) ((int)luaL_optinteger(L,narg,def))
++
++#ifdef LNUM_COMPLEX
++  LUALIB_API lua_Complex (luaL_checkcomplex) (lua_State *L, int narg);
++#endif
+ 
+ LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg);
+ LUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t);
+--- a/src/lbaselib.c
++++ b/src/lbaselib.c
+@@ -18,7 +18,9 @@
+ 
+ #include "lauxlib.h"
+ #include "lualib.h"
+-
++#include "llimits.h"
++#include "lobject.h"
++#include "lapi.h"
+ 
+ 
+ 
+@@ -54,20 +56,25 @@ static int luaB_tonumber (lua_State *L)
+   int base = luaL_optint(L, 2, 10);
+   if (base == 10) {  /* standard conversion */
+     luaL_checkany(L, 1);
+-    if (lua_isnumber(L, 1)) {
+-      lua_pushnumber(L, lua_tonumber(L, 1));
++    if (lua_isnumber(L, 1)) {       /* numeric string, or a number */
++      lua_pushvalue_as_number(L,1);     /* API extension (not to lose accuracy here) */
+       return 1;
+-    }
++	}
+   }
+   else {
+     const char *s1 = luaL_checkstring(L, 1);
+     char *s2;
+-    unsigned long n;
++    unsigned LUA_INTEGER n;
+     luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range");
+-    n = strtoul(s1, &s2, base);
++    n = lua_str2ul(s1, &s2, base);
+     if (s1 != s2) {  /* at least one valid digit? */
+       while (isspace((unsigned char)(*s2))) s2++;  /* skip trailing spaces */
+       if (*s2 == '\0') {  /* no invalid trailing characters? */
++	  
++		/* Push as number, there needs to be separate 'luaB_tointeger' for
++		 * when the caller wants to preserve the bits (matters if unsigned
++		 * values are used).
++		 */
+         lua_pushnumber(L, (lua_Number)n);
+         return 1;
+       }
+@@ -144,7 +151,7 @@ static int luaB_setfenv (lua_State *L) {
+   luaL_checktype(L, 2, LUA_TTABLE);
+   getfunc(L, 0);
+   lua_pushvalue(L, 2);
+-  if (lua_isnumber(L, 1) && lua_tonumber(L, 1) == 0) {
++  if (lua_isnumber(L, 1) && lua_tointeger(L, 1) == 0) {
+     /* change environment of current thread */
+     lua_pushthread(L);
+     lua_insert(L, -2);
+@@ -209,7 +216,7 @@ static int luaB_collectgarbage (lua_Stat
+       return 1;
+     }
+     default: {
+-      lua_pushnumber(L, res);
++      lua_pushinteger(L, res);
+       return 1;
+     }
+   }
+@@ -631,6 +638,8 @@ static void base_open (lua_State *L) {
+   luaL_register(L, "_G", base_funcs);
+   lua_pushliteral(L, LUA_VERSION);
+   lua_setglobal(L, "_VERSION");  /* set global _VERSION */
++  lua_pushliteral(L, LUA_LNUM);
++  lua_setglobal(L, "_LNUM");  /* "[complex] double|float|ldouble int32|int64" */
+   /* `ipairs' and `pairs' need auxiliary functions as upvalues */
+   auxopen(L, "ipairs", luaB_ipairs, ipairsaux);
+   auxopen(L, "pairs", luaB_pairs, luaB_next);
+--- a/src/lcode.c
++++ b/src/lcode.c
+@@ -22,13 +22,18 @@
+ #include "lopcodes.h"
+ #include "lparser.h"
+ #include "ltable.h"
++#include "lnum.h"
+ 
+ 
+ #define hasjumps(e)	((e)->t != (e)->f)
+ 
+-
+ static int isnumeral(expdesc *e) {
+-  return (e->k == VKNUM && e->t == NO_JUMP && e->f == NO_JUMP);
++  int ek=
++#ifdef LNUM_COMPLEX
++    (e->k == VKNUM2) ||
++#endif
++    (e->k == VKINT) || (e->k == VKNUM);
++  return (ek && e->t == NO_JUMP && e->f == NO_JUMP);
+ }
+ 
+ 
+@@ -231,12 +236,16 @@ static int addk (FuncState *fs, TValue *
+   TValue *idx = luaH_set(L, fs->h, k);
+   Proto *f = fs->f;
+   int oldsize = f->sizek;
+-  if (ttisnumber(idx)) {
+-    lua_assert(luaO_rawequalObj(&fs->f->k[cast_int(nvalue(idx))], v));
+-    return cast_int(nvalue(idx));
++  if (ttype(idx)==LUA_TNUMBER) {
++    luai_normalize(idx);
++    lua_assert( ttype(idx)==LUA_TINT );     /* had no fraction */
++  }
++  if (ttisint(idx)) {
++    lua_assert(luaO_rawequalObj(&fs->f->k[ivalue(idx)], v));
++    return cast_int(ivalue(idx));
+   }
+   else {  /* constant not found; create a new entry */
+-    setnvalue(idx, cast_num(fs->nk));
++    setivalue(idx, fs->nk);
+     luaM_growvector(L, f->k, fs->nk, f->sizek, TValue,
+                     MAXARG_Bx, "constant table overflow");
+     while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]);
+@@ -261,6 +270,21 @@ int luaK_numberK (FuncState *fs, lua_Num
+ }
+ 
+ 
++int luaK_integerK (FuncState *fs, lua_Integer r) {
++  TValue o;
++  setivalue(&o, r);
++  return addk(fs, &o, &o);
++}
++
++
++#ifdef LNUM_COMPLEX
++static int luaK_imagK (FuncState *fs, lua_Number r) {
++  TValue o;
++  setnvalue_complex(&o, r*I);
++  return addk(fs, &o, &o);
++}
++#endif
++
+ static int boolK (FuncState *fs, int b) {
+   TValue o;
+   setbvalue(&o, b);
+@@ -359,6 +383,16 @@ static void discharge2reg (FuncState *fs
+       luaK_codeABx(fs, OP_LOADK, reg, luaK_numberK(fs, e->u.nval));
+       break;
+     }
++    case VKINT: {
++      luaK_codeABx(fs, OP_LOADK, reg, luaK_integerK(fs, e->u.ival));
++      break;
++    }
++#ifdef LNUM_COMPLEX
++    case VKNUM2: {
++      luaK_codeABx(fs, OP_LOADK, reg, luaK_imagK(fs, e->u.nval));
++      break;
++    }
++#endif
+     case VRELOCABLE: {
+       Instruction *pc = &getcode(fs, e);
+       SETARG_A(*pc, reg);
+@@ -444,6 +478,10 @@ void luaK_exp2val (FuncState *fs, expdes
+ int luaK_exp2RK (FuncState *fs, expdesc *e) {
+   luaK_exp2val(fs, e);
+   switch (e->k) {
++#ifdef LNUM_COMPLEX
++    case VKNUM2:
++#endif
++    case VKINT:
+     case VKNUM:
+     case VTRUE:
+     case VFALSE:
+@@ -451,6 +489,10 @@ int luaK_exp2RK (FuncState *fs, expdesc
+       if (fs->nk <= MAXINDEXRK) {  /* constant fit in RK operand? */
+         e->u.s.info = (e->k == VNIL)  ? nilK(fs) :
+                       (e->k == VKNUM) ? luaK_numberK(fs, e->u.nval) :
++                      (e->k == VKINT) ? luaK_integerK(fs, e->u.ival) :
++#ifdef LNUM_COMPLEX
++                      (e->k == VKNUM2) ? luaK_imagK(fs, e->u.nval) :
++#endif
+                                         boolK(fs, (e->k == VTRUE));
+         e->k = VK;
+         return RKASK(e->u.s.info);
+@@ -540,7 +582,10 @@ void luaK_goiftrue (FuncState *fs, expde
+   int pc;  /* pc of last jump */
+   luaK_dischargevars(fs, e);
+   switch (e->k) {
+-    case VK: case VKNUM: case VTRUE: {
++#ifdef LNUM_COMPLEX
++    case VKNUM2:
++#endif
++    case VKINT: case VK: case VKNUM: case VTRUE: {
+       pc = NO_JUMP;  /* always true; do nothing */
+       break;
+     }
+@@ -590,7 +635,10 @@ static void codenot (FuncState *fs, expd
+       e->k = VTRUE;
+       break;
+     }
+-    case VK: case VKNUM: case VTRUE: {
++#ifdef LNUM_COMPLEX
++    case VKNUM2:
++#endif
++    case VKINT: case VK: case VKNUM: case VTRUE: {
+       e->k = VFALSE;
+       break;
+     }
+@@ -626,25 +674,70 @@ void luaK_indexed (FuncState *fs, expdes
+ 
+ static int constfolding (OpCode op, expdesc *e1, expdesc *e2) {
+   lua_Number v1, v2, r;
++  int vkres= VKNUM;
+   if (!isnumeral(e1) || !isnumeral(e2)) return 0;
+-  v1 = e1->u.nval;
+-  v2 = e2->u.nval;
++
++  /* real and imaginary parts don't mix. */
++#ifdef LNUM_COMPLEX
++  if (e1->k == VKNUM2) {
++    if ((op != OP_UNM) && (e2->k != VKNUM2)) return 0; 
++    vkres= VKNUM2; }
++  else if (e2->k == VKNUM2) { return 0; }
++#endif
++  if ((e1->k == VKINT) && (e2->k == VKINT)) {
++    lua_Integer i1= e1->u.ival, i2= e2->u.ival;
++    lua_Integer rr;
++    int done= 0;
++    /* Integer/integer calculations (may end up producing floating point) */
++    switch (op) {
++      case OP_ADD: done= try_addint( &rr, i1, i2 ); break;
++      case OP_SUB: done= try_subint( &rr, i1, i2 ); break;
++      case OP_MUL: done= try_mulint( &rr, i1, i2 ); break;
++      case OP_DIV: done= try_divint( &rr, i1, i2 ); break;
++      case OP_MOD: done= try_modint( &rr, i1, i2 ); break;
++      case OP_POW: done= try_powint( &rr, i1, i2 ); break;
++      case OP_UNM: done= try_unmint( &rr, i1 ); break;
++      default:     done= 0; break;
++    }
++    if (done) {
++      e1->u.ival = rr;  /* remained within integer range */
++      return 1;
++    }
++  }
++  v1 = (e1->k == VKINT) ? ((lua_Number)e1->u.ival) : e1->u.nval;
++  v2 = (e2->k == VKINT) ? ((lua_Number)e2->u.ival) : e2->u.nval;
++
+   switch (op) {
+     case OP_ADD: r = luai_numadd(v1, v2); break;
+     case OP_SUB: r = luai_numsub(v1, v2); break;
+-    case OP_MUL: r = luai_nummul(v1, v2); break;
++    case OP_MUL: 
++#ifdef LNUM_COMPLEX
++        if (vkres==VKNUM2) return 0;    /* leave to runtime (could do here, but not worth it?) */
++#endif
++        r = luai_nummul(v1, v2); break;
+     case OP_DIV:
+       if (v2 == 0) return 0;  /* do not attempt to divide by 0 */
+-      r = luai_numdiv(v1, v2); break;
++#ifdef LNUM_COMPLEX
++        if (vkres==VKNUM2) return 0;    /* leave to runtime */
++#endif
++        r = luai_numdiv(v1, v2); break;
+     case OP_MOD:
+       if (v2 == 0) return 0;  /* do not attempt to divide by 0 */
++#ifdef LNUM_COMPLEX
++      if (vkres==VKNUM2) return 0;    /* leave to runtime */
++#endif
+       r = luai_nummod(v1, v2); break;
+-    case OP_POW: r = luai_numpow(v1, v2); break;
++    case OP_POW: 
++#ifdef LNUM_COMPLEX
++      if (vkres==VKNUM2) return 0;    /* leave to runtime */
++#endif
++      r = luai_numpow(v1, v2); break;
+     case OP_UNM: r = luai_numunm(v1); break;
+     case OP_LEN: return 0;  /* no constant folding for 'len' */
+     default: lua_assert(0); r = 0; break;
+   }
+   if (luai_numisnan(r)) return 0;  /* do not attempt to produce NaN */
++  e1->k = cast(expkind,vkres);
+   e1->u.nval = r;
+   return 1;
+ }
+@@ -688,7 +781,8 @@ static void codecomp (FuncState *fs, OpC
+ 
+ void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) {
+   expdesc e2;
+-  e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0;
++  e2.t = e2.f = NO_JUMP; e2.k = VKINT; e2.u.ival = 0;
++
+   switch (op) {
+     case OPR_MINUS: {
+       if (!isnumeral(e))
+--- a/src/lcode.h
++++ b/src/lcode.h
+@@ -71,6 +71,6 @@ LUAI_FUNC void luaK_prefix (FuncState *f
+ LUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v);
+ LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, expdesc *v2);
+ LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore);
+-
++LUAI_FUNC int luaK_integerK (FuncState *fs, lua_Integer r);
+ 
+ #endif
+--- a/src/ldebug.c
++++ b/src/ldebug.c
+@@ -183,7 +183,7 @@ static void collectvalidlines (lua_State
+     int *lineinfo = f->l.p->lineinfo;
+     int i;
+     for (i=0; i<f->l.p->sizelineinfo; i++)
+-      setbvalue(luaH_setnum(L, t, lineinfo[i]), 1);
++      setbvalue(luaH_setint(L, t, lineinfo[i]), 1);
+     sethvalue(L, L->top, t); 
+   }
+   incr_top(L);
+@@ -566,7 +566,7 @@ static int isinstack (CallInfo *ci, cons
+ 
+ void luaG_typeerror (lua_State *L, const TValue *o, const char *op) {
+   const char *name = NULL;
+-  const char *t = luaT_typenames[ttype(o)];
++  const char *t = luaT_typenames[ttype_ext(o)];
+   const char *kind = (isinstack(L->ci, o)) ?
+                          getobjname(L, L->ci, cast_int(o - L->base), &name) :
+                          NULL;
+@@ -594,8 +594,8 @@ void luaG_aritherror (lua_State *L, cons
+ 
+ 
+ int luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) {
+-  const char *t1 = luaT_typenames[ttype(p1)];
+-  const char *t2 = luaT_typenames[ttype(p2)];
++  const char *t1 = luaT_typenames[ttype_ext(p1)];
++  const char *t2 = luaT_typenames[ttype_ext(p2)];
+   if (t1[2] == t2[2])
+     luaG_runerror(L, "attempt to compare two %s values", t1);
+   else
+--- a/src/ldo.c
++++ b/src/ldo.c
+@@ -220,9 +220,9 @@ static StkId adjust_varargs (lua_State *
+     luaD_checkstack(L, p->maxstacksize);
+     htab = luaH_new(L, nvar, 1);  /* create `arg' table */
+     for (i=0; i<nvar; i++)  /* put extra arguments into `arg' table */
+-      setobj2n(L, luaH_setnum(L, htab, i+1), L->top - nvar + i);
++      setobj2n(L, luaH_setint(L, htab, i+1), L->top - nvar + i);
+     /* store counter in field `n' */
+-    setnvalue(luaH_setstr(L, htab, luaS_newliteral(L, "n")), cast_num(nvar));
++    setivalue(luaH_setstr(L, htab, luaS_newliteral(L, "n")), nvar);
+   }
+ #endif
+   /* move fixed parameters to final position */
+--- a/src/ldump.c
++++ b/src/ldump.c
+@@ -52,6 +52,11 @@ static void DumpNumber(lua_Number x, Dum
+  DumpVar(x,D);
+ }
+ 
++static void DumpInteger(lua_Integer x, DumpState* D)
++{
++ DumpVar(x,D);
++}
++
+ static void DumpVector(const void* b, int n, size_t size, DumpState* D)
+ {
+  DumpInt(n,D);
+@@ -93,8 +98,11 @@ static void DumpConstants(const Proto* f
+ 	DumpChar(bvalue(o),D);
+ 	break;
+    case LUA_TNUMBER:
+-	DumpNumber(nvalue(o),D);
++	DumpNumber(nvalue_fast(o),D);
+ 	break;
++   case LUA_TINT:
++	DumpInteger(ivalue(o),D);
++    break;
+    case LUA_TSTRING:
+ 	DumpString(rawtsvalue(o),D);
+ 	break;
+--- a/src/liolib.c
++++ b/src/liolib.c
+@@ -9,6 +9,7 @@
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
++#include <ctype.h>
+ 
+ #define liolib_c
+ #define LUA_LIB
+@@ -18,7 +19,8 @@
+ #include "lauxlib.h"
+ #include "lualib.h"
+ 
+-
++#include "lnum.h"
++#include "llex.h"
+ 
+ #define IO_INPUT	1
+ #define IO_OUTPUT	2
+@@ -269,6 +271,13 @@ static int io_lines (lua_State *L) {
+ ** =======================================================
+ */
+ 
++/*
++* Many problems if we intend the same 'n' format specifier (see 'file:read()')
++* to work for both FP and integer numbers, without losing their accuracy. So
++* we don't. 'n' reads numbers as floating points, 'i' as integers. Old code
++* remains valid, but won't provide full integer accuracy (this only matters
++* with float FP and/or 64-bit integers).
++*/
+ 
+ static int read_number (lua_State *L, FILE *f) {
+   lua_Number d;
+@@ -282,6 +291,43 @@ static int read_number (lua_State *L, FI
+   }
+ }
+ 
++static int read_integer (lua_State *L, FILE *f) {
++  lua_Integer i;
++  if (fscanf(f, LUA_INTEGER_SCAN, &i) == 1) {
++    lua_pushinteger(L, i);
++    return 1;
++  }
++  else return 0;  /* read fails */
++}
++
++#ifdef LNUM_COMPLEX
++static int read_complex (lua_State *L, FILE *f) {
++  /* NNN / NNNi / NNN+MMMi / NNN-MMMi */
++  lua_Number a,b;
++  if (fscanf(f, LUA_NUMBER_SCAN, &a) == 1) {
++    int c=fgetc(f);
++    switch(c) {
++        case 'i':
++            lua_pushcomplex(L, a*I);
++            return 1;
++        case '+':
++        case '-':
++            /* "i" is consumed if at the end; just 'NNN+MMM' will most likely
++             * behave as if "i" was there? (TBD: test)
++             */
++            if (fscanf(f, LUA_NUMBER_SCAN "i", &b) == 1) {
++                lua_pushcomplex(L, a+ (c=='+' ? b:-b)*I);
++                return 1;
++            }
++    }
++    ungetc( c,f );
++    lua_pushnumber(L,a);  /*real part only*/
++    return 1;
++  }
++  return 0;  /* read fails */
++}
++#endif
++
+ 
+ static int test_eof (lua_State *L, FILE *f) {
+   int c = getc(f);
+@@ -355,6 +401,14 @@ static int g_read (lua_State *L, FILE *f
+           case 'n':  /* number */
+             success = read_number(L, f);
+             break;
++          case 'i':  /* integer (full accuracy) */
++            success = read_integer(L, f);
++            break;
++#ifdef LNUM_COMPLEX
++          case 'c':  /* complex */
++            success = read_complex(L, f);
++            break;
++#endif
+           case 'l':  /* line */
+             success = read_line(L, f);
+             break;
+@@ -415,9 +469,10 @@ static int g_write (lua_State *L, FILE *
+   int status = 1;
+   for (; nargs--; arg++) {
+     if (lua_type(L, arg) == LUA_TNUMBER) {
+-      /* optimization: could be done exactly as for strings */
+-      status = status &&
+-          fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0;
++      if (lua_isinteger(L,arg))
++          status = status && fprintf(f, LUA_INTEGER_FMT, lua_tointeger(L, arg)) > 0;
++      else
++          status = status && fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0;
+     }
+     else {
+       size_t l;
+@@ -460,7 +515,7 @@ static int f_setvbuf (lua_State *L) {
+   static const char *const modenames[] = {"no", "full", "line", NULL};
+   FILE *f = tofile(L);
+   int op = luaL_checkoption(L, 2, NULL, modenames);
+-  lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE);
++  size_t sz = luaL_optint32(L, 3, LUAL_BUFFERSIZE);
+   int res = setvbuf(f, NULL, mode[op], sz);
+   return pushresult(L, res == 0, NULL);
+ }
+--- a/src/llex.c
++++ b/src/llex.c
+@@ -22,6 +22,7 @@
+ #include "lstring.h"
+ #include "ltable.h"
+ #include "lzio.h"
++#include "lnum.h"
+ 
+ 
+ 
+@@ -34,13 +35,17 @@
+ 
+ 
+ /* ORDER RESERVED */
+-const char *const luaX_tokens [] = {
++static const char *const luaX_tokens [] = {
+     "and", "break", "do", "else", "elseif",
+     "end", "false", "for", "function", "if",
+     "in", "local", "nil", "not", "or", "repeat",
+     "return", "then", "true", "until", "while",
+     "..", "...", "==", ">=", "<=", "~=",
+     "<number>", "<name>", "<string>", "<eof>",
++    "<integer>",
++#ifdef LNUM_COMPLEX
++    "<number2>",
++#endif
+     NULL
+ };
+ 
+@@ -90,7 +95,11 @@ static const char *txtToken (LexState *l
+   switch (token) {
+     case TK_NAME:
+     case TK_STRING:
++    case TK_INT:
+     case TK_NUMBER:
++#ifdef LNUM_COMPLEX
++    case TK_NUMBER2:
++#endif
+       save(ls, '\0');
+       return luaZ_buffer(ls->buff);
+     default:
+@@ -175,23 +184,27 @@ static void buffreplace (LexState *ls, c
+     if (p[n] == from) p[n] = to;
+ }
+ 
+-
+-static void trydecpoint (LexState *ls, SemInfo *seminfo) {
++/* TK_NUMBER (/ TK_NUMBER2) */
++static int trydecpoint (LexState *ls, SemInfo *seminfo) {
+   /* format error: try to update decimal point separator */
+   struct lconv *cv = localeconv();
+   char old = ls->decpoint;
++  int ret;
+   ls->decpoint = (cv ? cv->decimal_point[0] : '.');
+   buffreplace(ls, old, ls->decpoint);  /* try updated decimal separator */
+-  if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) {
++  ret= luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r, NULL);
++  if (!ret) {
+     /* format error with correct decimal point: no more options */
+     buffreplace(ls, ls->decpoint, '.');  /* undo change (for error message) */
+     luaX_lexerror(ls, "malformed number", TK_NUMBER);
+   }
++  return ret;
+ }
+ 
+ 
+-/* LUA_NUMBER */
+-static void read_numeral (LexState *ls, SemInfo *seminfo) {
++/* TK_NUMBER / TK_INT (/TK_NUMBER2) */
++static int read_numeral (LexState *ls, SemInfo *seminfo) {
++  int ret;
+   lua_assert(isdigit(ls->current));
+   do {
+     save_and_next(ls);
+@@ -202,8 +215,9 @@ static void read_numeral (LexState *ls,
+     save_and_next(ls);
+   save(ls, '\0');
+   buffreplace(ls, '.', ls->decpoint);  /* follow locale for decimal point */
+-  if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r))  /* format error? */
+-    trydecpoint(ls, seminfo); /* try to update decimal point separator */
++  ret= luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r, &seminfo->i );
++  if (!ret) return trydecpoint(ls, seminfo); /* try to update decimal point separator */
++  return ret;
+ }
+ 
+ 
+@@ -331,6 +345,7 @@ static void read_string (LexState *ls, i
+ }
+ 
+ 
++/* char / TK_* */
+ static int llex (LexState *ls, SemInfo *seminfo) {
+   luaZ_resetbuffer(ls->buff);
+   for (;;) {
+@@ -402,8 +417,7 @@ static int llex (LexState *ls, SemInfo *
+         }
+         else if (!isdigit(ls->current)) return '.';
+         else {
+-          read_numeral(ls, seminfo);
+-          return TK_NUMBER;
++          return read_numeral(ls, seminfo);
+         }
+       }
+       case EOZ: {
+@@ -416,8 +430,7 @@ static int llex (LexState *ls, SemInfo *
+           continue;
+         }
+         else if (isdigit(ls->current)) {
+-          read_numeral(ls, seminfo);
+-          return TK_NUMBER;
++          return read_numeral(ls, seminfo);
+         }
+         else if (isalpha(ls->current) || ls->current == '_') {
+           /* identifier or reserved word */
+--- a/src/llex.h
++++ b/src/llex.h
+@@ -29,19 +29,22 @@ enum RESERVED {
+   TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE,
+   /* other terminal symbols */
+   TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_NUMBER,
+-  TK_NAME, TK_STRING, TK_EOS
++  TK_NAME, TK_STRING, TK_EOS, TK_INT
++#ifdef LNUM_COMPLEX
++  , TK_NUMBER2   /* imaginary constants: Ni */ 
++#endif
+ };
+ 
+ /* number of reserved words */
+ #define NUM_RESERVED	(cast(int, TK_WHILE-FIRST_RESERVED+1))
+ 
+ 
+-/* array with token `names' */
+-LUAI_DATA const char *const luaX_tokens [];
+-
+-
++/* SemInfo is a local data structure of 'llex.c', used for carrying a string
++ * or a number. A separate token (TK_*) will tell, how to interpret the data.
++ */      
+ typedef union {
+   lua_Number r;
++  lua_Integer i;
+   TString *ts;
+ } SemInfo;  /* semantics information */
+ 
+--- a/src/llimits.h
++++ b/src/llimits.h
+@@ -49,6 +49,7 @@ typedef LUAI_USER_ALIGNMENT_T L_Umaxalig
+ 
+ /* result of a `usual argument conversion' over lua_Number */
+ typedef LUAI_UACNUMBER l_uacNumber;
++typedef LUAI_UACINTEGER l_uacInteger;
+ 
+ 
+ /* internal assertions for in-house debugging */
+@@ -80,7 +81,6 @@ typedef LUAI_UACNUMBER l_uacNumber;
+ #define cast_int(i)	cast(int, (i))
+ 
+ 
+-
+ /*
+ ** type for virtual-machine instructions
+ ** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h)
+--- a/src/lmathlib.c
++++ b/src/lmathlib.c
+@@ -4,7 +4,6 @@
+ ** See Copyright Notice in lua.h
+ */
+ 
+-
+ #include <stdlib.h>
+ #include <math.h>
+ 
+@@ -16,113 +15,210 @@
+ #include "lauxlib.h"
+ #include "lualib.h"
+ 
++/* 'luai_vectpow()' as a replacement for 'cpow()'. Defined in the header; we
++ * don't intrude the code libs internal functions.
++ */
++#ifdef LNUM_COMPLEX
++# include "lnum.h"    
++#endif
+ 
+ #undef PI
+-#define PI (3.14159265358979323846)
+-#define RADIANS_PER_DEGREE (PI/180.0)
+-
+-
++#ifdef LNUM_FLOAT
++# define PI (3.14159265358979323846F)
++#elif defined(M_PI)
++# define PI M_PI
++#else
++# define PI (3.14159265358979323846264338327950288)
++#endif
++#define RADIANS_PER_DEGREE (PI/180)
++
++#undef HUGE
++#ifdef LNUM_FLOAT
++# define HUGE HUGE_VALF
++#elif defined(LNUM_LDOUBLE)
++# define HUGE HUGE_VALL
++#else
++# define HUGE HUGE_VAL
++#endif
+ 
+ static int math_abs (lua_State *L) {
+-  lua_pushnumber(L, fabs(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++  lua_pushnumber(L, _LF(cabs) (luaL_checkcomplex(L,1)));
++#else
++  lua_pushnumber(L, _LF(fabs) (luaL_checknumber(L, 1)));
++#endif
+   return 1;
+ }
+ 
+ static int math_sin (lua_State *L) {
+-  lua_pushnumber(L, sin(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++  lua_pushcomplex(L, _LF(csin) (luaL_checkcomplex(L,1)));
++#else
++  lua_pushnumber(L, _LF(sin) (luaL_checknumber(L, 1)));
++#endif
+   return 1;
+ }
+ 
+ static int math_sinh (lua_State *L) {
+-  lua_pushnumber(L, sinh(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++  lua_pushcomplex(L, _LF(csinh) (luaL_checkcomplex(L,1)));
++#else
++  lua_pushnumber(L, _LF(sinh) (luaL_checknumber(L, 1)));
++#endif
+   return 1;
+ }
+ 
+ static int math_cos (lua_State *L) {
+-  lua_pushnumber(L, cos(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++  lua_pushcomplex(L, _LF(ccos) (luaL_checkcomplex(L,1)));
++#else
++  lua_pushnumber(L, _LF(cos) (luaL_checknumber(L, 1)));
++#endif
+   return 1;
+ }
+ 
+ static int math_cosh (lua_State *L) {
+-  lua_pushnumber(L, cosh(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++  lua_pushcomplex(L, _LF(ccosh) (luaL_checkcomplex(L,1)));
++#else
++  lua_pushnumber(L, _LF(cosh) (luaL_checknumber(L, 1)));
++#endif
+   return 1;
+ }
+ 
+ static int math_tan (lua_State *L) {
+-  lua_pushnumber(L, tan(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++  lua_pushcomplex(L, _LF(ctan) (luaL_checkcomplex(L,1)));
++#else
++  lua_pushnumber(L, _LF(tan) (luaL_checknumber(L, 1)));
++#endif
+   return 1;
+ }
+ 
+ static int math_tanh (lua_State *L) {
+-  lua_pushnumber(L, tanh(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++  lua_pushcomplex(L, _LF(ctanh) (luaL_checkcomplex(L,1)));
++#else
++  lua_pushnumber(L, _LF(tanh) (luaL_checknumber(L, 1)));
++#endif
+   return 1;
+ }
+ 
+ static int math_asin (lua_State *L) {
+-  lua_pushnumber(L, asin(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++  lua_pushcomplex(L, _LF(casin) (luaL_checkcomplex(L,1)));
++#else
++  lua_pushnumber(L, _LF(asin) (luaL_checknumber(L, 1)));
++#endif
+   return 1;
+ }
+ 
+ static int math_acos (lua_State *L) {
+-  lua_pushnumber(L, acos(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++  lua_pushcomplex(L, _LF(cacos) (luaL_checkcomplex(L,1)));
++#else
++  lua_pushnumber(L, _LF(acos) (luaL_checknumber(L, 1)));
++#endif
+   return 1;
+ }
+ 
+ static int math_atan (lua_State *L) {
+-  lua_pushnumber(L, atan(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++  lua_pushcomplex(L, _LF(catan) (luaL_checkcomplex(L,1)));
++#else
++  lua_pushnumber(L, _LF(atan) (luaL_checknumber(L, 1)));
++#endif
+   return 1;
+ }
+ 
+ static int math_atan2 (lua_State *L) {
+-  lua_pushnumber(L, atan2(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
++  /* scalars only */
++  lua_pushnumber(L, _LF(atan2) (luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
+   return 1;
+ }
+ 
+ static int math_ceil (lua_State *L) {
+-  lua_pushnumber(L, ceil(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++  lua_Complex v= luaL_checkcomplex(L, 1);
++  lua_pushcomplex(L, _LF(ceil) (_LF(creal)(v)) + _LF(ceil) (_LF(cimag)(v))*I);
++#else
++  lua_pushnumber(L, _LF(ceil) (luaL_checknumber(L, 1)));
++#endif
+   return 1;
+ }
+ 
+ static int math_floor (lua_State *L) {
+-  lua_pushnumber(L, floor(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++  lua_Complex v= luaL_checkcomplex(L, 1);
++  lua_pushcomplex(L, _LF(floor) (_LF(creal)(v)) + _LF(floor) (_LF(cimag)(v))*I);
++#else
++  lua_pushnumber(L, _LF(floor) (luaL_checknumber(L, 1)));
++#endif
+   return 1;
+ }
+ 
+-static int math_fmod (lua_State *L) {
+-  lua_pushnumber(L, fmod(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
++static int math_fmod (lua_State *L) {  
++  /* scalars only */
++  lua_pushnumber(L, _LF(fmod) (luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
+   return 1;
+ }
+ 
+ static int math_modf (lua_State *L) {
+-  double ip;
+-  double fp = modf(luaL_checknumber(L, 1), &ip);
++  /* scalars only */
++  lua_Number ip;
++  lua_Number fp = _LF(modf) (luaL_checknumber(L, 1), &ip);
+   lua_pushnumber(L, ip);
+   lua_pushnumber(L, fp);
+   return 2;
+ }
+ 
+ static int math_sqrt (lua_State *L) {
+-  lua_pushnumber(L, sqrt(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++  lua_pushcomplex(L, _LF(csqrt) (luaL_checkcomplex(L,1)));
++#else
++  lua_pushnumber(L, _LF(sqrt) (luaL_checknumber(L, 1)));
++#endif
+   return 1;
+ }
+ 
+ static int math_pow (lua_State *L) {
+-  lua_pushnumber(L, pow(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
++#ifdef LNUM_COMPLEX
++  /* C99 'cpow' gives somewhat inaccurate results (i.e. (-1)^2 = -1+1.2246467991474e-16i). 
++  * 'luai_vectpow' smoothens such, reusing it is the reason we need to #include "lnum.h".
++  */
++  lua_pushcomplex(L, luai_vectpow(luaL_checkcomplex(L,1), luaL_checkcomplex(L,2)));
++#else
++  lua_pushnumber(L, _LF(pow) (luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
++#endif
+   return 1;
+ }
+ 
+ static int math_log (lua_State *L) {
+-  lua_pushnumber(L, log(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++  lua_pushcomplex(L, _LF(clog) (luaL_checkcomplex(L,1)));
++#else
++  lua_pushnumber(L, _LF(log) (luaL_checknumber(L, 1)));
++#endif
+   return 1;
+ }
+ 
+ static int math_log10 (lua_State *L) {
+-  lua_pushnumber(L, log10(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++  /* Not in standard <complex.h> , but easy to calculate: log_a(x) = log_b(x) / log_b(a) 
++  */
++  lua_pushcomplex(L, _LF(clog) (luaL_checkcomplex(L,1)) / _LF(log) (10));
++#else
++  lua_pushnumber(L, _LF(log10) (luaL_checknumber(L, 1)));
++#endif
+   return 1;
+ }
+ 
+ static int math_exp (lua_State *L) {
+-  lua_pushnumber(L, exp(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++  lua_pushcomplex(L, _LF(cexp) (luaL_checkcomplex(L,1)));
++#else
++  lua_pushnumber(L, _LF(exp) (luaL_checknumber(L, 1)));
++#endif
+   return 1;
+ }
+ 
+@@ -138,19 +234,20 @@ static int math_rad (lua_State *L) {
+ 
+ static int math_frexp (lua_State *L) {
+   int e;
+-  lua_pushnumber(L, frexp(luaL_checknumber(L, 1), &e));
++  lua_pushnumber(L, _LF(frexp) (luaL_checknumber(L, 1), &e));
+   lua_pushinteger(L, e);
+   return 2;
+ }
+ 
+ static int math_ldexp (lua_State *L) {
+-  lua_pushnumber(L, ldexp(luaL_checknumber(L, 1), luaL_checkint(L, 2)));
++  lua_pushnumber(L, _LF(ldexp) (luaL_checknumber(L, 1), luaL_checkint(L, 2)));
+   return 1;
+ }
+ 
+ 
+ 
+ static int math_min (lua_State *L) {
++  /* scalars only */
+   int n = lua_gettop(L);  /* number of arguments */
+   lua_Number dmin = luaL_checknumber(L, 1);
+   int i;
+@@ -165,6 +262,7 @@ static int math_min (lua_State *L) {
+ 
+ 
+ static int math_max (lua_State *L) {
++  /* scalars only */
+   int n = lua_gettop(L);  /* number of arguments */
+   lua_Number dmax = luaL_checknumber(L, 1);
+   int i;
+@@ -182,25 +280,20 @@ static int math_random (lua_State *L) {
+   /* the `%' avoids the (rare) case of r==1, and is needed also because on
+      some systems (SunOS!) `rand()' may return a value larger than RAND_MAX */
+   lua_Number r = (lua_Number)(rand()%RAND_MAX) / (lua_Number)RAND_MAX;
+-  switch (lua_gettop(L)) {  /* check number of arguments */
+-    case 0: {  /* no arguments */
+-      lua_pushnumber(L, r);  /* Number between 0 and 1 */
+-      break;
+-    }
+-    case 1: {  /* only upper limit */
+-      int u = luaL_checkint(L, 1);
+-      luaL_argcheck(L, 1<=u, 1, "interval is empty");
+-      lua_pushnumber(L, floor(r*u)+1);  /* int between 1 and `u' */
+-      break;
+-    }
+-    case 2: {  /* lower and upper limits */
+-      int l = luaL_checkint(L, 1);
+-      int u = luaL_checkint(L, 2);
+-      luaL_argcheck(L, l<=u, 2, "interval is empty");
+-      lua_pushnumber(L, floor(r*(u-l+1))+l);  /* int between `l' and `u' */
+-      break;
+-    }
+-    default: return luaL_error(L, "wrong number of arguments");
++  int n= lua_gettop(L);  /* number of arguments */
++  if (n==0) {	/* no arguments: range [0,1) */
++    lua_pushnumber(L, r);
++  } else if (n<=2) {	/* int range [1,u] or [l,u] */
++    int l= n==1 ? 1 : luaL_checkint(L, 1);
++    int u = luaL_checkint(L, n);
++    int tmp;
++    lua_Number d;
++    luaL_argcheck(L, l<=u, n, "interval is empty");
++    d= _LF(floor)(r*(u-l+1));
++    lua_number2int(tmp,d);
++    lua_pushinteger(L, l+tmp);
++  } else {
++    return luaL_error(L, "wrong number of arguments");
+   }
+   return 1;
+ }
+@@ -211,6 +304,66 @@ static int math_randomseed (lua_State *L
+   return 0;
+ }
+ 
++/* 
++* Lua 5.1 does not have acosh, asinh, atanh for scalars (not ANSI C)
++*/
++#if __STDC_VERSION__ >= 199901L
++static int math_acosh (lua_State *L) {
++# ifdef LNUM_COMPLEX
++  lua_pushcomplex(L, _LF(cacosh) (luaL_checkcomplex(L,1)));
++# else
++  lua_pushnumber(L, _LF(acosh) (luaL_checknumber(L,1)));
++# endif
++  return 1;
++}
++static int math_asinh (lua_State *L) {
++# ifdef LNUM_COMPLEX
++  lua_pushcomplex(L, _LF(casinh) (luaL_checkcomplex(L,1)));
++# else
++  lua_pushnumber(L, _LF(asinh) (luaL_checknumber(L,1)));
++# endif
++  return 1;
++}
++static int math_atanh (lua_State *L) {
++# ifdef LNUM_COMPLEX
++  lua_pushcomplex(L, _LF(catanh) (luaL_checkcomplex(L,1)));
++# else
++  lua_pushnumber(L, _LF(atanh) (luaL_checknumber(L,1)));
++# endif
++  return 1;
++}
++#endif
++
++/* 
++ * C99 complex functions, not covered above.
++*/
++#ifdef LNUM_COMPLEX
++static int math_arg (lua_State *L) {
++  lua_pushnumber(L, _LF(carg) (luaL_checkcomplex(L,1)));
++  return 1;
++}
++
++static int math_imag (lua_State *L) {
++  lua_pushnumber(L, _LF(cimag) (luaL_checkcomplex(L,1)));
++  return 1;
++}
++
++static int math_real (lua_State *L) {
++  lua_pushnumber(L, _LF(creal) (luaL_checkcomplex(L,1)));
++  return 1;
++}
++
++static int math_conj (lua_State *L) {
++  lua_pushcomplex(L, _LF(conj) (luaL_checkcomplex(L,1)));
++  return 1;
++}
++
++static int math_proj (lua_State *L) {
++  lua_pushcomplex(L, _LF(cproj) (luaL_checkcomplex(L,1)));
++  return 1;
++}
++#endif
++
+ 
+ static const luaL_Reg mathlib[] = {
+   {"abs",   math_abs},
+@@ -241,6 +394,18 @@ static const luaL_Reg mathlib[] = {
+   {"sqrt",  math_sqrt},
+   {"tanh",   math_tanh},
+   {"tan",   math_tan},
++#if __STDC_VERSION__ >= 199901L
++  {"acosh",  math_acosh},
++  {"asinh",  math_asinh},
++  {"atanh",  math_atanh},
++#endif
++#ifdef LNUM_COMPLEX
++  {"arg",   math_arg},
++  {"imag",  math_imag},
++  {"real",  math_real},
++  {"conj",  math_conj},
++  {"proj",  math_proj},
++#endif
+   {NULL, NULL}
+ };
+ 
+@@ -252,8 +417,10 @@ LUALIB_API int luaopen_math (lua_State *
+   luaL_register(L, LUA_MATHLIBNAME, mathlib);
+   lua_pushnumber(L, PI);
+   lua_setfield(L, -2, "pi");
+-  lua_pushnumber(L, HUGE_VAL);
++  lua_pushnumber(L, HUGE);
+   lua_setfield(L, -2, "huge");
++  lua_pushinteger(L, LUA_INTEGER_MAX );
++  lua_setfield(L, -2, "hugeint");
+ #if defined(LUA_COMPAT_MOD)
+   lua_getfield(L, -1, "fmod");
+   lua_setfield(L, -2, "mod");
+--- /dev/null
++++ b/src/lnum.c
+@@ -0,0 +1,312 @@
++/*
++** $Id: lnum.c,v ... $
++** Internal number model
++** See Copyright Notice in lua.h
++*/
++
++#include <stdlib.h>
++#include <math.h>
++#include <ctype.h>
++#include <string.h>
++#include <stdio.h>
++#include <errno.h>
++
++#define lnum_c
++#define LUA_CORE
++
++#include "lua.h"
++#include "llex.h"
++#include "lnum.h"
++
++/*
++** lua_real2str converts a (non-complex) number to a string.
++** lua_str2real converts a string to a (non-complex) number.
++*/
++#define lua_real2str(s,n)  sprintf((s), LUA_NUMBER_FMT, (n))
++
++/*
++* Note: Only 'strtod()' is part of ANSI C; others are C99 and
++* may need '--std=c99' compiler setting (at least on Ubuntu 7.10).
++* 
++* Visual C++ 2008 Express does not have 'strtof()', nor 'strtold()'.
++* References to '_strtold()' exist but don't compile. It seems best
++* to leave Windows users with DOUBLE only (or compile with MinGW).
++*
++* In practise, using '(long double)strtod' is a risky thing, since
++* it will cause accuracy loss in reading in numbers, and such losses
++* will pile up in later processing. Get a real 'strtold()' or don't
++* use that mode at all.
++*/
++#ifdef LNUM_DOUBLE
++# define lua_str2real	strtod
++#elif defined(LNUM_FLOAT)
++# define lua_str2real	strtof
++#elif defined(LNUM_LDOUBLE)
++# define lua_str2real	strtold
++#endif
++
++#define lua_integer2str(s,v) sprintf((s), LUA_INTEGER_FMT, (v))
++
++/* 's' is expected to be LUAI_MAXNUMBER2STR long (enough for any number)
++*/
++void luaO_num2buf( char *s, const TValue *o )
++{
++  lua_Number n;
++  lua_assert( ttisnumber(o) );
++
++  /* Reason to handle integers differently is not only speed, but accuracy as
++   * well. We want to make any integer tostring() without roundings, at all.
++   */
++  if (ttisint(o)) {
++    lua_integer2str( s, ivalue(o) );
++    return;
++  }
++  n= nvalue_fast(o);
++  lua_real2str(s, n);
++
++#ifdef LNUM_COMPLEX
++  lua_Number n2= nvalue_img_fast(o);
++  if (n2!=0) {   /* Postfix with +-Ni */
++      int re0= (n == 0);
++      char *s2= re0 ? s : strchr(s,'\0'); 
++      if ((!re0) && (n2>0)) *s2++= '+';
++      lua_real2str( s2, n2 );
++      strcat(s2,"i");
++  }
++#endif
++}
++
++/*
++* If a LUA_TNUMBER has integer value, give it.
++*/
++int /*bool*/ tt_integer_valued( const TValue *o, lua_Integer *ref ) {
++  lua_Number d;
++  lua_Integer i;
++
++  lua_assert( ttype(o)==LUA_TNUMBER );
++  lua_assert( ref );
++#ifdef LNUM_COMPLEX
++  if (nvalue_img_fast(o)!=0) return 0;
++#endif
++  d= nvalue_fast(o);
++  lua_number2integer(i, d);
++  if (cast_num(i) == d) {
++    *ref= i; return 1;
++  }
++  return 0;
++}
++
++/* 
++ * Lua 5.1.3 (using 'strtod()') allows 0x+hex but not 0+octal. This is good,
++ * and we should NOT use 'autobase' 0 with 'strtoul[l]()' for this reason.
++ *
++ * Lua 5.1.3 allows '0x...' numbers to overflow and lose precision; this is not
++ * good. On Visual C++ 2008, 'strtod()' does not even take them in. Better to
++ * require hex values to fit 'lua_Integer' or give an error that they don't?
++ *
++ * Full hex range (0 .. 0xff..ff) is stored as integers, not to lose any bits.
++ * Numerical value of 0xff..ff will be -1, if used in calculations.
++ * 
++ * Returns: TK_INT for a valid integer, '*endptr_ref' updated
++ *          TK_NUMBER for seemingly numeric, to be parsed as floating point
++ *          0 for bad characters, not a number (or '0x' out of range)
++ */
++static int luaO_str2i (const char *s, lua_Integer *res, char **endptr_ref) {
++  char *endptr;
++  /* 'v' gets ULONG_MAX on possible overflow (which is > LUA_INTEGER_MAX);
++   * we don't have to check 'errno' here.
++   */
++  unsigned LUA_INTEGER v= lua_str2ul(s, &endptr, 10);
++  if (endptr == s) return 0;  /* nothing numeric */
++  if (v==0 && *endptr=='x') {
++    errno= 0;   /* needs to be set, 'strtoul[l]' does not clear it */
++    v= lua_str2ul(endptr+1, &endptr, 16);  /* retry as hex, unsigned range */
++    if (errno==ERANGE) {   /* clamped to 0xff..ff */
++#if (defined(LNUM_INT32) && !defined(LNUM_FLOAT)) || defined(LNUM_LDOUBLE)
++      return TK_NUMBER; /* Allow to be read as floating point (has more integer range) */
++#else
++      return 0;  /* Reject the number */
++#endif
++    }
++  } else if ((v > LUA_INTEGER_MAX) || (*endptr && (!isspace(*endptr)))) {
++    return TK_NUMBER;	/* not in signed range, or has '.', 'e' etc. trailing */
++  }
++  *res= (lua_Integer)v;
++  *endptr_ref= endptr;
++  return TK_INT;
++}
++
++/* 0 / TK_NUMBER / TK_INT (/ TK_NUMBER2) */
++int luaO_str2d (const char *s, lua_Number *res_n, lua_Integer *res_i) {
++  char *endptr;
++  int ret= TK_NUMBER;
++  /* Check integers first, if caller is allowing. 
++   * If 'res2'==NULL, they're only looking for floating point. 
++   */
++  if (res_i) {
++    ret= luaO_str2i(s,res_i,&endptr);
++    if (ret==0) return 0;
++  }
++  if (ret==TK_NUMBER) {
++    lua_assert(res_n);
++    /* Note: Visual C++ 2008 Express 'strtod()' does not read in "0x..."
++     *       numbers; it will read '0' and spit 'x' as endptr.
++     *       This means hex constants not fitting in 'lua_Integer' won't 
++     *       be read in at all. What to do?
++     */
++    *res_n = lua_str2real(s, &endptr);
++    if (endptr == s) return 0;  /* conversion failed */
++    /* Visual C++ 2008 'strtod()' does not allow "0x..." input. */
++#if defined(_MSC_VER) && !defined(LNUM_FLOAT) && !defined(LNUM_INT64)
++    if (*res_n==0 && *endptr=='x') {
++      /* Hex constant too big for 'lua_Integer' but that could fit in 'lua_Number'
++       * integer bits 
++       */
++      unsigned __int64 v= _strtoui64( s, &endptr, 16 );
++      /* We just let > 64 bit values be clamped to _UI64_MAX (MSDN does not say 'errno'==ERANGE would be set) */
++      *res_n= cast_num(v);
++      if (*res_n != v) return 0;    /* Would have lost accuracy */
++    }
++#endif
++#ifdef LNUM_COMPLEX
++    if (*endptr == 'i') { endptr++; ret= TK_NUMBER2; }
++#endif
++  }
++  if (*endptr) {
++    while (isspace(cast(unsigned char, *endptr))) endptr++;
++    if (*endptr) return 0;  /* invalid trail */
++  }
++  return ret;
++}
++
++
++/* Functions for finding out, when integer operations remain in range
++ * (and doing them).
++ */
++int try_addint( lua_Integer *r, lua_Integer ib, lua_Integer ic ) {
++  /* Signed int overflow is undefined behavior, so catch it without causing it. */
++  if (ic>0)  { if (ib > LUA_INTEGER_MAX - ic) return 0; /*overflow, use floats*/ }
++  else       { if (ib < LUA_INTEGER_MIN - ic) return 0; }
++  *r = ib + ic;
++  return 1;
++}
++
++int try_subint( lua_Integer *r, lua_Integer ib, lua_Integer ic ) {
++  /* Signed int overflow is undefined behavior, so catch it without causing it. */
++  if (ic>0)  { if (ib < LUA_INTEGER_MIN + ic) return 0; /*overflow, use floats*/ }
++  else       { if (ib > LUA_INTEGER_MAX + ic) return 0; }
++  *r = ib - ic;
++  return 1;
++}
++
++int try_mulint( lua_Integer *r, lua_Integer ib, lua_Integer ic ) {
++  if (ib!=LUA_INTEGER_MIN && ic!=LUA_INTEGER_MIN) {
++    lua_Integer b= luai_abs(ib), c= luai_abs(ic);
++    if ( (ib==0) || (LUA_INTEGER_MAX/b >= c) ) {
++      *r= ib*ic;  /* no overflow */
++      return 1;
++    }
++  } else if (ib==0 || ic==0) {
++    *r= 0; return 1;
++  }
++
++  /* Result can be LUA_INTEGER_MIN; if it is, calculating it using floating 
++   * point will not cause accuracy loss.
++   */
++  if ( luai_nummul( cast_num(ib), cast_num(ic) ) == LUA_INTEGER_MIN ) {
++    *r= LUA_INTEGER_MIN;
++    return 1;
++  }
++  return 0;
++}
++
++int try_divint( lua_Integer *r, lua_Integer ib, lua_Integer ic ) {
++  /* N/0: leave to float side, to give an error
++  */
++  if (ic==0) return 0;
++
++  /* N/LUA_INTEGER_MIN: always non-integer results, or 0 or +1
++  */
++  if (ic==LUA_INTEGER_MIN) {
++    if (ib==LUA_INTEGER_MIN) { *r=1; return 1; }
++    if (ib==0) { *r=0; return 1; }
++
++  /* LUA_INTEGER_MIN (-2^31|63)/N: calculate using float side (either the division 
++   *    causes non-integer results, or there is no accuracy loss in int->fp->int
++   *    conversions (N=2,4,8,..,256 and N=2^30,2^29,..2^23).
++   */
++  } else if (ib==LUA_INTEGER_MIN) {
++    lua_Number d= luai_numdiv( cast_num(LUA_INTEGER_MIN), cast_num(ic) );
++    lua_Integer i; lua_number2integer(i,d);
++    if (cast_num(i)==d) { *r= i; return 1; }
++  
++  } else {
++    /* Note: We _can_ use ANSI C mod here, even on negative values, since
++     *       we only test for == 0 (the sign would be implementation dependent).
++     */
++     if (ib%ic == 0) { *r= ib/ic; return 1; }
++  }
++
++  return 0;
++}
++
++int try_modint( lua_Integer *r, lua_Integer ib, lua_Integer ic ) {
++  if (ic!=0) {
++    /* ANSI C can be trusted when b%c==0, or when values are non-negative. 
++     * b - (floor(b/c) * c)
++     *   -->
++     * + +: b - (b/c) * c (b % c can be used)
++     * - -: b - (b/c) * c (b % c could work, but not defined by ANSI C)
++     * 0 -: b - (b/c) * c (=0, b % c could work, but not defined by ANSI C)
++     * - +: b - (b/c-1) * c (when b!=-c)
++     * + -: b - (b/c-1) * c (when b!=-c)
++     *
++     * o MIN%MIN ends up 0, via overflow in calcs but that does not matter.
++     * o MIN%MAX ends up MAX-1 (and other such numbers), also after overflow,
++     *   but that does not matter, results do.
++     */
++    lua_Integer v= ib % ic;
++    if ( v!=0 && (ib<0 || ic<0) ) {
++      v= ib - ((ib/ic) - ((ib<=0 && ic<0) ? 0:1)) * ic;
++    }      
++    /* Result should always have same sign as 2nd argument. (PIL2) */
++    lua_assert( (v<0) ? (ic<0) : (v>0) ? (ic>0) : 1 );
++    *r= v;
++    return 1;
++  }
++  return 0;  /* let float side return NaN */
++}
++
++int try_powint( lua_Integer *r, lua_Integer ib, lua_Integer ic ) {
++
++    /* In FLOAT/INT32 or FLOAT|DOUBLE/INT64 modes, calculating integer powers 
++     * via FP realm may lose accuracy (i.e. 7^11 = 1977326743, which fits int32
++     * but not 23-bit float mantissa). 
++     *
++     * The current solution is dumb, but it works and uses little code. Use of
++     * integer powers is not anticipated to be very frequent (apart from 2^x,
++     * which is separately optimized).
++     */
++  if (ib==0) *r=0;
++  else if (ic<0) return 0;  /* FP realm */
++  else if (ib==2 && ic < (int)sizeof(lua_Integer)*8-1) *r= ((lua_Integer)1)<<ic;   /* 1,2,4,...2^30 | 2^62 optimization */
++  else if (ic==0) *r=1;
++  else if (luai_abs(ib)==1) *r= (ic%2) ? ib:1;
++  else {
++    lua_Integer x= ib;
++    while( --ic ) {
++      if (!try_mulint( &x, x, ib ))
++        return 0; /* FP realm */
++    }
++    *r= x;
++  }
++  return 1;
++}
++
++int try_unmint( lua_Integer *r, lua_Integer ib ) {
++  /* Negating LUA_INTEGER_MIN leaves the range. */
++  if ( ib != LUA_INTEGER_MIN )  
++    { *r= -ib; return 1; }
++  return 0;
++}
++
+--- /dev/null
++++ b/src/lnum.h
+@@ -0,0 +1,116 @@
++/*
++** $Id: lnum.h,v ... $
++** Internal Number model
++** See Copyright Notice in lua.h
++*/
++
++#ifndef lnum_h
++#define lnum_h
++
++#include <math.h>
++
++#include "lobject.h"
++
++/*
++** The luai_num* macros define the primitive operations over 'lua_Number's
++** (not 'lua_Integer's, not 'lua_Complex').
++*/
++#define luai_numadd(a,b)	((a)+(b))
++#define luai_numsub(a,b)	((a)-(b))
++#define luai_nummul(a,b)	((a)*(b))
++#define luai_numdiv(a,b)	((a)/(b))
++#define luai_nummod(a,b)	((a) - _LF(floor)((a)/(b))*(b))
++#define luai_numpow(a,b)	(_LF(pow)(a,b))
++#define luai_numunm(a)		(-(a))
++#define luai_numeq(a,b)	    ((a)==(b))
++#define luai_numlt(a,b)	    ((a)<(b))
++#define luai_numle(a,b)	    ((a)<=(b))
++#define luai_numisnan(a)	(!luai_numeq((a), (a)))
++
++int try_addint( lua_Integer *r, lua_Integer ib, lua_Integer ic );
++int try_subint( lua_Integer *r, lua_Integer ib, lua_Integer ic );
++int try_mulint( lua_Integer *r, lua_Integer ib, lua_Integer ic );
++int try_divint( lua_Integer *r, lua_Integer ib, lua_Integer ic );
++int try_modint( lua_Integer *r, lua_Integer ib, lua_Integer ic );
++int try_powint( lua_Integer *r, lua_Integer ib, lua_Integer ic );
++int try_unmint( lua_Integer *r, lua_Integer ib );
++
++#ifdef LNUM_COMPLEX
++  static inline lua_Complex luai_vectunm( lua_Complex a ) { return -a; }
++  static inline lua_Complex luai_vectadd( lua_Complex a, lua_Complex b ) { return a+b; }
++  static inline lua_Complex luai_vectsub( lua_Complex a, lua_Complex b ) { return a-b; }
++  static inline lua_Complex luai_vectmul( lua_Complex a, lua_Complex b ) { return a*b; }
++  static inline lua_Complex luai_vectdiv( lua_Complex a, lua_Complex b ) { return a/b; }
++
++/* 
++ * C99 does not provide modulus for complex numbers. It most likely is not
++ * meaningful at all.
++ */
++
++/* 
++ * Complex power
++ *
++ * C99 'cpow' gives inaccurate results for many common cases s.a. (1i)^2 -> 
++ * -1+1.2246467991474e-16i (OS X 10.4, gcc 4.0.1 build 5367)
++ * 
++ * [(a+bi)^(c+di)] = (r^c) * exp(-d*t) * cos(c*t + d*ln(r)) +
++ *                 = (r^c) * exp(-d*t) * sin(c*t + d*ln(r)) *i
++ * r = sqrt(a^2+b^2), t = arctan( b/a )
++ * 
++ * Reference: <http://home.att.net/~srschmitt/complexnumbers.html>
++ * Could also be calculated using: x^y = exp(ln(x)*y)
++ *
++ * Note: Defined here (and not in .c) so 'lmathlib.c' can share the 
++ *       implementation.
++ */
++  static inline
++  lua_Complex luai_vectpow( lua_Complex a, lua_Complex b )
++  {
++# if 1
++    lua_Number ar= _LF(creal)(a), ai= _LF(cimag)(a);
++    lua_Number br= _LF(creal)(b), bi= _LF(cimag)(b);
++    
++    if (ai==0 && bi==0) {     /* a^c (real) */
++        return luai_numpow( ar, br );
++    } 
++
++    int br_int= (int)br;
++    
++    if ( ai!=0 && bi==0 && br_int==br && br_int!=0 && br_int!=INT_MIN ) { 
++        /* (a+bi)^N, N = { +-1,+-2, ... +-INT_MAX } 
++        */
++        lua_Number k= luai_numpow( _LF(sqrt) (ar*ar + ai*ai), br );
++        lua_Number cos_z, sin_z;
++
++        /* Situation depends upon c (N) in the following manner:
++         * 
++         * N%4==0                                => cos(c*t)=1, sin(c*t)=0
++         * (N*sign(b))%4==1 or (N*sign(b))%4==-3 => cos(c*t)=0, sin(c*t)=1
++         * N%4==2 or N%4==-2                     => cos(c*t)=-1, sin(c*t)=0
++         * (N*sign(b))%4==-1 or (N*sign(b))%4==3 => cos(c*t)=0, sin(c*t)=-1
++         */
++      int br_int_abs = br_int<0 ? -br_int:br_int;
++      
++      switch( (br_int_abs%4) * (br_int<0 ? -1:1) * (ai<0 ? -1:1) ) {
++        case 0:             cos_z=1, sin_z=0; break;
++        case 2: case -2:    cos_z=-1, sin_z=0; break;
++        case 1: case -3:    cos_z=0, sin_z=1; break;
++        case 3: case -1:    cos_z=0, sin_z=-1; break;
++        default:            lua_assert(0); return 0;
++      }
++      return k*cos_z + (k*sin_z)*I;
++    }
++# endif
++    return _LF(cpow) ( a, b );
++  }
++#endif
++
++LUAI_FUNC int luaO_str2d (const char *s, lua_Number *res1, lua_Integer *res2);
++LUAI_FUNC void luaO_num2buf( char *s, const TValue *o );
++
++LUAI_FUNC int /*bool*/ tt_integer_valued( const TValue *o, lua_Integer *ref );
++
++#define luai_normalize(o) \
++{ lua_Integer _i; if (tt_integer_valued(o,&_i)) setivalue(o,_i); }
++
++#endif
+--- /dev/null
++++ b/src/lnum_config.h
+@@ -0,0 +1,221 @@
++/*
++** $Id: lnum_config.h,v ... $
++** Internal Number model
++** See Copyright Notice in lua.h
++*/
++
++#ifndef lnum_config_h
++#define lnum_config_h
++
++/*
++** Default number modes
++*/
++#if (!defined LNUM_DOUBLE) && (!defined LNUM_FLOAT) && (!defined LNUM_LDOUBLE)
++# define LNUM_FLOAT
++#endif
++#if (!defined LNUM_INT16) && (!defined LNUM_INT32) && (!defined LNUM_INT64)
++# define LNUM_INT32
++#endif
++
++/*
++** Require C99 mode for COMPLEX, FLOAT and LDOUBLE (only DOUBLE is ANSI C).
++*/
++#if defined(LNUM_COMPLEX) && (__STDC_VERSION__ < 199901L)
++# error "Need C99 for complex (use '--std=c99' or similar)"
++#elif defined(LNUM_LDOUBLE) && (__STDC_VERSION__ < 199901L) && !defined(_MSC_VER)
++# error "Need C99 for 'long double' (use '--std=c99' or similar)"
++#elif defined(LNUM_FLOAT) && (__STDC_VERSION__ < 199901L)
++/* LNUM_FLOAT not supported on Windows */
++# error "Need C99 for 'float' (use '--std=c99' or similar)"
++#endif
++ 
++/*
++** Number mode identifier to accompany the version string.
++*/
++#ifdef LNUM_COMPLEX
++# define _LNUM1 "complex "
++#else
++# define _LNUM1 ""
++#endif
++#ifdef LNUM_DOUBLE
++# define _LNUM2 "double"
++#elif defined(LNUM_FLOAT)
++# define _LNUM2 "float"
++#elif defined(LNUM_LDOUBLE)
++# define _LNUM2 "ldouble"
++#endif
++#ifdef LNUM_INT32
++# define _LNUM3 "int32"
++#elif defined(LNUM_INT64)
++# define _LNUM3 "int64"
++#elif defined(LNUM_INT16)
++# define _LNUM3 "int16"
++#endif
++#define LUA_LNUM _LNUM1 _LNUM2 " " _LNUM3
++
++/*
++** LUA_NUMBER is the type of floating point number in Lua
++** LUA_NUMBER_SCAN is the format for reading numbers.
++** LUA_NUMBER_FMT is the format for writing numbers.
++*/
++#ifdef LNUM_FLOAT
++# define LUA_NUMBER         float
++# define LUA_NUMBER_SCAN    "%f"
++# define LUA_NUMBER_FMT     "%g"  
++#elif (defined LNUM_DOUBLE)
++# define LUA_NUMBER	        double
++# define LUA_NUMBER_SCAN    "%lf"
++# define LUA_NUMBER_FMT     "%.14g"
++#elif (defined LNUM_LDOUBLE)
++# define LUA_NUMBER         long double
++# define LUA_NUMBER_SCAN    "%Lg"
++# define LUA_NUMBER_FMT     "%.20Lg"
++#endif
++
++
++/* 
++** LUAI_MAXNUMBER2STR: size of a buffer fitting any number->string result.
++**
++**  double:  24 (sign, x.xxxxxxxxxxxxxxe+nnnn, and \0)
++**  int64:   21 (19 digits, sign, and \0)
++**  long double: 43 for 128-bit (sign, x.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxe+nnnn, and \0)
++**           30 for 80-bit (sign, x.xxxxxxxxxxxxxxxxxxxxe+nnnn, and \0)
++*/
++#ifdef LNUM_LDOUBLE
++# define _LUAI_MN2S 44
++#else
++# define _LUAI_MN2S 24
++#endif
++
++#ifdef LNUM_COMPLEX
++# define LUAI_MAXNUMBER2STR (2*_LUAI_MN2S)
++#else
++# define LUAI_MAXNUMBER2STR _LUAI_MN2S
++#endif
++
++/*
++** LUA_INTEGER is the integer type used by lua_pushinteger/lua_tointeger/lua_isinteger.
++** LUA_INTEGER_SCAN is the format for reading integers
++** LUA_INTEGER_FMT is the format for writing integers
++**
++** Note: Visual C++ 2005 does not have 'strtoull()', use '_strtoui64()' instead.
++*/
++#ifdef LNUM_INT32
++# if LUAI_BITSINT > 16
++#  define LUA_INTEGER   int
++#  define LUA_INTEGER_SCAN "%d"
++#  define LUA_INTEGER_FMT "%d"
++# else
++/* Note: 'LUA_INTEGER' being 'ptrdiff_t' (as in Lua 5.1) causes problems with
++ *       'printf()' operations. Also 'unsigned ptrdiff_t' is invalid.
++ */
++#  define LUA_INTEGER   long
++#  define LUA_INTEGER_SCAN "%ld"
++#  define LUA_INTEGER_FMT "%ld"
++# endif
++# define LUA_INTEGER_MAX 0x7FFFFFFF             /* 2^31-1 */
++/* */
++#elif defined(LNUM_INT64)
++# define LUA_INTEGER	long long
++# ifdef _MSC_VER
++#  define lua_str2ul    _strtoui64
++# else
++#  define lua_str2ul    strtoull
++# endif
++# define LUA_INTEGER_SCAN "%lld"
++# define LUA_INTEGER_FMT "%lld"
++# define LUA_INTEGER_MAX 0x7fffffffffffffffLL       /* 2^63-1 */ 
++# define LUA_INTEGER_MIN (-LUA_INTEGER_MAX - 1LL)   /* -2^63 */
++/* */
++#elif defined(LNUM_INT16)
++# if LUAI_BITSINT > 16
++#  define LUA_INTEGER    short
++#  define LUA_INTEGER_SCAN "%hd"
++#  define LUA_INTEGER_FMT "%hd"
++# else
++#  define LUA_INTEGER    int
++#  define LUA_INTEGER_SCAN "%d"
++#  define LUA_INTEGER_FMT "%d"
++# endif
++# define LUA_INTEGER_MAX 0x7FFF             /* 2^16-1 */
++#endif
++
++#ifndef lua_str2ul
++# define lua_str2ul (unsigned LUA_INTEGER)strtoul
++#endif
++#ifndef LUA_INTEGER_MIN
++# define LUA_INTEGER_MIN (-LUA_INTEGER_MAX -1)  /* -2^16|32 */
++#endif
++
++/*
++@@ lua_number2int is a macro to convert lua_Number to int.
++@@ lua_number2integer is a macro to convert lua_Number to lua_Integer.
++** CHANGE them if you know a faster way to convert a lua_Number to
++** int (with any rounding method and without throwing errors) in your
++** system. In Pentium machines, a naive typecast from double to int
++** in C is extremely slow, so any alternative is worth trying.
++*/
++
++/* On a Pentium, resort to a trick */
++#if defined(LNUM_DOUBLE) && !defined(LUA_ANSI) && !defined(__SSE2__) && \
++    (defined(__i386) || defined (_M_IX86) || defined(__i386__))
++
++/* On a Microsoft compiler, use assembler */
++# if defined(_MSC_VER)
++#  define lua_number2int(i,d)   __asm fld d   __asm fistp i
++# else
++
++/* the next trick should work on any Pentium, but sometimes clashes
++   with a DirectX idiosyncrasy */
++union luai_Cast { double l_d; long l_l; };
++#  define lua_number2int(i,d) \
++  { volatile union luai_Cast u; u.l_d = (d) + 6755399441055744.0; (i) = u.l_l; }
++# endif
++
++# ifndef LNUM_INT64
++#  define lua_number2integer    lua_number2int
++# endif
++
++/* this option always works, but may be slow */
++#else
++# define lua_number2int(i,d)        ((i)=(int)(d))
++#endif
++
++/* Note: Some compilers (OS X gcc 4.0?) may choke on double->long long conversion 
++ *       since it can lose precision. Others do require 'long long' there.  
++ */
++#ifndef lua_number2integer
++# define lua_number2integer(i,d)    ((i)=(lua_Integer)(d))
++#endif
++
++/*
++** 'luai_abs()' to give absolute value of 'lua_Integer'
++*/
++#ifdef LNUM_INT32
++# define luai_abs abs
++#elif defined(LNUM_INT64) && (__STDC_VERSION__ >= 199901L)
++# define luai_abs llabs
++#else
++# define luai_abs(v) ((v) >= 0 ? (v) : -(v))
++#endif
++
++/*
++** LUAI_UACNUMBER is the result of an 'usual argument conversion' over a number.
++** LUAI_UACINTEGER the same, over an integer.
++*/
++#define LUAI_UACNUMBER	double
++#define LUAI_UACINTEGER long
++
++/* ANSI C only has math funcs for 'double. C99 required for float and long double
++ * variants.
++ */
++#ifdef LNUM_DOUBLE
++# define _LF(name) name
++#elif defined(LNUM_FLOAT)
++# define _LF(name) name ## f
++#elif defined(LNUM_LDOUBLE)
++# define _LF(name) name ## l
++#endif
++
++#endif
++
+--- a/src/lobject.c
++++ b/src/lobject.c
+@@ -21,7 +21,8 @@
+ #include "lstate.h"
+ #include "lstring.h"
+ #include "lvm.h"
+-
++#include "llex.h"
++#include "lnum.h"
+ 
+ 
+ const TValue luaO_nilobject_ = {{NULL}, LUA_TNIL};
+@@ -70,12 +71,31 @@ int luaO_log2 (unsigned int x) {
+ 
+ 
+ int luaO_rawequalObj (const TValue *t1, const TValue *t2) {
+-  if (ttype(t1) != ttype(t2)) return 0;
++  if (!ttype_ext_same(t1,t2)) return 0;
+   else switch (ttype(t1)) {
+     case LUA_TNIL:
+       return 1;
++    case LUA_TINT:
++      if (ttype(t2)==LUA_TINT)
++        return ivalue(t1) == ivalue(t2);
++      else {  /* t1:int, t2:num */
++#ifdef LNUM_COMPLEX
++        if (nvalue_img_fast(t2) != 0) return 0;
++#endif
++        /* Avoid doing accuracy losing cast, if possible. */
++        lua_Integer tmp;
++        if (tt_integer_valued(t2,&tmp)) 
++          return ivalue(t1) == tmp;
++        else
++          return luai_numeq( cast_num(ivalue(t1)), nvalue_fast(t2) );
++        }
+     case LUA_TNUMBER:
+-      return luai_numeq(nvalue(t1), nvalue(t2));
++        if (ttype(t2)==LUA_TINT)
++          return luaO_rawequalObj(t2, t1);  /* swap LUA_TINT to left */
++#ifdef LNUM_COMPLEX
++        if (!luai_numeq(nvalue_img_fast(t1), nvalue_img_fast(t2))) return 0;
++#endif
++        return luai_numeq(nvalue_fast(t1), nvalue_fast(t2));
+     case LUA_TBOOLEAN:
+       return bvalue(t1) == bvalue(t2);  /* boolean true must be 1 !! */
+     case LUA_TLIGHTUSERDATA:
+@@ -86,21 +106,6 @@ int luaO_rawequalObj (const TValue *t1,
+   }
+ }
+ 
+-
+-int luaO_str2d (const char *s, lua_Number *result) {
+-  char *endptr;
+-  *result = lua_str2number(s, &endptr);
+-  if (endptr == s) return 0;  /* conversion failed */
+-  if (*endptr == 'x' || *endptr == 'X')  /* maybe an hexadecimal constant? */
+-    *result = cast_num(strtoul(s, &endptr, 16));
+-  if (*endptr == '\0') return 1;  /* most common case */
+-  while (isspace(cast(unsigned char, *endptr))) endptr++;
+-  if (*endptr != '\0') return 0;  /* invalid trailing characters? */
+-  return 1;
+-}
+-
+-
+-
+ static void pushstr (lua_State *L, const char *str) {
+   setsvalue2s(L, L->top, luaS_new(L, str));
+   incr_top(L);
+@@ -131,7 +136,11 @@ const char *luaO_pushvfstring (lua_State
+         break;
+       }
+       case 'd': {
+-        setnvalue(L->top, cast_num(va_arg(argp, int)));
++        /* This is tricky for 64-bit integers; maybe they even cannot be
++         * supported on all compilers; depends on the conversions applied to
++         * variable argument lists. TBD: test!
++         */
++        setivalue(L->top, (lua_Integer) va_arg(argp, l_uacInteger));
+         incr_top(L);
+         break;
+       }
+@@ -212,3 +221,4 @@ void luaO_chunkid (char *out, const char
+     }
+   }
+ }
++
+--- a/src/lobject.h
++++ b/src/lobject.h
+@@ -17,7 +17,11 @@
+ 
+ 
+ /* tags for values visible from Lua */
+-#define LAST_TAG	LUA_TTHREAD
++#if LUA_TINT > LUA_TTHREAD
++# define LAST_TAG   LUA_TINT
++#else
++# define LAST_TAG	LUA_TTHREAD
++#endif
+ 
+ #define NUM_TAGS	(LAST_TAG+1)
+ 
+@@ -59,7 +63,12 @@ typedef struct GCheader {
+ typedef union {
+   GCObject *gc;
+   void *p;
++#ifdef LNUM_COMPLEX
++  lua_Complex n;
++#else
+   lua_Number n;
++#endif
++  lua_Integer i;
+   int b;
+ } Value;
+ 
+@@ -77,7 +86,11 @@ typedef struct lua_TValue {
+ 
+ /* Macros to test type */
+ #define ttisnil(o)	(ttype(o) == LUA_TNIL)
+-#define ttisnumber(o)	(ttype(o) == LUA_TNUMBER)
++#define ttisint(o) (ttype(o) == LUA_TINT)
++#define ttisnumber(o) ((ttype(o) == LUA_TINT) || (ttype(o) == LUA_TNUMBER))
++#ifdef LNUM_COMPLEX
++# define ttiscomplex(o) ((ttype(o) == LUA_TNUMBER) && (nvalue_img_fast(o)!=0))
++#endif
+ #define ttisstring(o)	(ttype(o) == LUA_TSTRING)
+ #define ttistable(o)	(ttype(o) == LUA_TTABLE)
+ #define ttisfunction(o)	(ttype(o) == LUA_TFUNCTION)
+@@ -90,7 +103,25 @@ typedef struct lua_TValue {
+ #define ttype(o)	((o)->tt)
+ #define gcvalue(o)	check_exp(iscollectable(o), (o)->value.gc)
+ #define pvalue(o)	check_exp(ttislightuserdata(o), (o)->value.p)
+-#define nvalue(o)	check_exp(ttisnumber(o), (o)->value.n)
++
++#define ttype_ext(o) ( ttype(o) == LUA_TINT ? LUA_TNUMBER : ttype(o) )
++#define ttype_ext_same(o1,o2) ( (ttype(o1)==ttype(o2)) || (ttisnumber(o1) && ttisnumber(o2)) )
++
++/* '_fast' variants are for cases where 'ttype(o)' is known to be LUA_TNUMBER.
++ */
++#ifdef LNUM_COMPLEX
++#  define nvalue_complex_fast(o) check_exp( ttype(o)==LUA_TNUMBER, (o)->value.n )   
++#  define nvalue_fast(o)     ( _LF(creal) ( nvalue_complex_fast(o) ) )
++#  define nvalue_img_fast(o) ( _LF(cimag) ( nvalue_complex_fast(o) ) )
++#  define nvalue_complex(o) check_exp( ttisnumber(o), (ttype(o)==LUA_TINT) ? (o)->value.i : (o)->value.n )
++#  define nvalue_img(o) check_exp( ttisnumber(o), (ttype(o)==LUA_TINT) ? 0 : _LF(cimag)( (o)->value.n ) ) 
++#  define nvalue(o) check_exp( ttisnumber(o), (ttype(o)==LUA_TINT) ? cast_num((o)->value.i) : _LF(creal)((o)->value.n) ) 
++#else
++# define nvalue(o)	check_exp( ttisnumber(o), (ttype(o)==LUA_TINT) ? cast_num((o)->value.i) : (o)->value.n )
++# define nvalue_fast(o) check_exp( ttype(o)==LUA_TNUMBER, (o)->value.n )   
++#endif
++#define ivalue(o)	check_exp( ttype(o)==LUA_TINT, (o)->value.i )
++
+ #define rawtsvalue(o)	check_exp(ttisstring(o), &(o)->value.gc->ts)
+ #define tsvalue(o)	(&rawtsvalue(o)->tsv)
+ #define rawuvalue(o)	check_exp(ttisuserdata(o), &(o)->value.gc->u)
+@@ -116,8 +147,27 @@ typedef struct lua_TValue {
+ /* Macros to set values */
+ #define setnilvalue(obj) ((obj)->tt=LUA_TNIL)
+ 
+-#define setnvalue(obj,x) \
+-  { TValue *i_o=(obj); i_o->value.n=(x); i_o->tt=LUA_TNUMBER; }
++/* Must not have side effects, 'x' may be expression.
++*/
++#define setivalue(obj,x) \
++    { TValue *i_o=(obj); i_o->value.i=(x); i_o->tt=LUA_TINT; }
++
++# define setnvalue(obj,x) \
++    { TValue *i_o=(obj); i_o->value.n= (x); i_o->tt=LUA_TNUMBER; }
++
++/* Note: Complex always has "inline", both are C99.
++*/
++#ifdef LNUM_COMPLEX
++  static inline void setnvalue_complex_fast( TValue *obj, lua_Complex x ) {
++    lua_assert( _LF(cimag)(x) != 0 );
++    obj->value.n= x; obj->tt= LUA_TNUMBER;
++  }
++  static inline void setnvalue_complex( TValue *obj, lua_Complex x ) {
++    if (_LF(cimag)(x) == 0) { setnvalue(obj, _LF(creal)(x)); }
++    else { obj->value.n= x; obj->tt= LUA_TNUMBER; }
++  }
++#endif
++
+ 
+ #define setpvalue(obj,x) \
+   { TValue *i_o=(obj); i_o->value.p=(x); i_o->tt=LUA_TLIGHTUSERDATA; }
+@@ -155,9 +205,6 @@ typedef struct lua_TValue {
+     i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TPROTO; \
+     checkliveness(G(L),i_o); }
+ 
+-
+-
+-
+ #define setobj(L,obj1,obj2) \
+   { const TValue *o2=(obj2); TValue *o1=(obj1); \
+     o1->value = o2->value; o1->tt=o2->tt; \
+@@ -185,8 +232,11 @@ typedef struct lua_TValue {
+ 
+ #define setttype(obj, tt) (ttype(obj) = (tt))
+ 
+-
+-#define iscollectable(o)	(ttype(o) >= LUA_TSTRING)
++#if LUA_TINT >= LUA_TSTRING
++# define iscollectable(o)	((ttype(o) >= LUA_TSTRING) && (ttype(o) != LUA_TINT))
++#else
++# define iscollectable(o)	(ttype(o) >= LUA_TSTRING)
++#endif
+ 
+ 
+ 
+@@ -370,12 +420,10 @@ LUAI_FUNC int luaO_log2 (unsigned int x)
+ LUAI_FUNC int luaO_int2fb (unsigned int x);
+ LUAI_FUNC int luaO_fb2int (int x);
+ LUAI_FUNC int luaO_rawequalObj (const TValue *t1, const TValue *t2);
+-LUAI_FUNC int luaO_str2d (const char *s, lua_Number *result);
+ LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt,
+                                                        va_list argp);
+ LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...);
+ LUAI_FUNC void luaO_chunkid (char *out, const char *source, size_t len);
+ 
+-
+ #endif
+ 
+--- a/src/loslib.c
++++ b/src/loslib.c
+@@ -186,15 +186,30 @@ static int os_time (lua_State *L) {
+   }
+   if (t == (time_t)(-1))
+     lua_pushnil(L);
+-  else
+-    lua_pushnumber(L, (lua_Number)t);
++  else {
++     /* On float systems the pushed value must be an integer, NOT a number.
++      * Otherwise, accuracy is lost in the time_t->float conversion.
++      */
++#ifdef LNUM_FLOAT
++     lua_pushinteger(L, (lua_Integer) t);
++#else
++     lua_pushnumber(L, (lua_Number) t);
++#endif
++     }
+   return 1;
+ }
+ 
+ 
+ static int os_difftime (lua_State *L) {
++#ifdef LNUM_FLOAT
++  lua_Integer i= (lua_Integer)
++    difftime( (time_t)(luaL_checkinteger(L, 1)),
++              (time_t)(luaL_optinteger(L, 2, 0)));
++  lua_pushinteger(L, i);
++#else
+   lua_pushnumber(L, difftime((time_t)(luaL_checknumber(L, 1)),
+                              (time_t)(luaL_optnumber(L, 2, 0))));
++#endif
+   return 1;
+ }
+ 
+--- a/src/lparser.c
++++ b/src/lparser.c
+@@ -33,7 +33,6 @@
+ 
+ #define luaY_checklimit(fs,v,l,m)	if ((v)>(l)) errorlimit(fs,l,m)
+ 
+-
+ /*
+ ** nodes for block list (list of active blocks)
+ */
+@@ -72,7 +71,7 @@ static void errorlimit (FuncState *fs, i
+   const char *msg = (fs->f->linedefined == 0) ?
+     luaO_pushfstring(fs->L, "main function has more than %d %s", limit, what) :
+     luaO_pushfstring(fs->L, "function at line %d has more than %d %s",
+-                            fs->f->linedefined, limit, what);
++                            (fs->f->linedefined), limit, what);
+   luaX_lexerror(fs->ls, msg, 0);
+ }
+ 
+@@ -733,6 +732,18 @@ static void simpleexp (LexState *ls, exp
+       v->u.nval = ls->t.seminfo.r;
+       break;
+     }
++    case TK_INT: {
++      init_exp(v, VKINT, 0);
++      v->u.ival = ls->t.seminfo.i;
++      break;
++    }
++#ifdef LNUM_COMPLEX
++    case TK_NUMBER2: {
++      init_exp(v, VKNUM2, 0);
++      v->u.nval = ls->t.seminfo.r;
++      break;
++    }
++#endif
+     case TK_STRING: {
+       codestring(ls, v, ls->t.seminfo.ts);
+       break;
+@@ -1079,7 +1090,7 @@ static void fornum (LexState *ls, TStrin
+   if (testnext(ls, ','))
+     exp1(ls);  /* optional step */
+   else {  /* default step = 1 */
+-    luaK_codeABx(fs, OP_LOADK, fs->freereg, luaK_numberK(fs, 1));
++    luaK_codeABx(fs, OP_LOADK, fs->freereg, luaK_integerK(fs, 1));
+     luaK_reserveregs(fs, 1);
+   }
+   forbody(ls, base, line, 1, 1);
+--- a/src/lparser.h
++++ b/src/lparser.h
+@@ -31,7 +31,11 @@ typedef enum {
+   VRELOCABLE,	/* info = instruction pc */
+   VNONRELOC,	/* info = result register */
+   VCALL,	/* info = instruction pc */
+-  VVARARG	/* info = instruction pc */
++  VVARARG,	/* info = instruction pc */
++  VKINT     /* ival = integer value */
++#ifdef LNUM_COMPLEX
++  ,VKNUM2   /* nval = imaginary value */
++#endif
+ } expkind;
+ 
+ typedef struct expdesc {
+@@ -39,6 +43,7 @@ typedef struct expdesc {
+   union {
+     struct { int info, aux; } s;
+     lua_Number nval;
++    lua_Integer ival;
+   } u;
+   int t;  /* patch list of `exit when true' */
+   int f;  /* patch list of `exit when false' */
+--- a/src/lstrlib.c
++++ b/src/lstrlib.c
+@@ -43,8 +43,8 @@ static ptrdiff_t posrelat (ptrdiff_t pos
+ static int str_sub (lua_State *L) {
+   size_t l;
+   const char *s = luaL_checklstring(L, 1, &l);
+-  ptrdiff_t start = posrelat(luaL_checkinteger(L, 2), l);
+-  ptrdiff_t end = posrelat(luaL_optinteger(L, 3, -1), l);
++  ptrdiff_t start = posrelat(luaL_checkint32(L, 2), l);
++  ptrdiff_t end = posrelat(luaL_optint32(L, 3, -1), l);
+   if (start < 1) start = 1;
+   if (end > (ptrdiff_t)l) end = (ptrdiff_t)l;
+   if (start <= end)
+@@ -106,8 +106,8 @@ static int str_rep (lua_State *L) {
+ static int str_byte (lua_State *L) {
+   size_t l;
+   const char *s = luaL_checklstring(L, 1, &l);
+-  ptrdiff_t posi = posrelat(luaL_optinteger(L, 2, 1), l);
+-  ptrdiff_t pose = posrelat(luaL_optinteger(L, 3, posi), l);
++  ptrdiff_t posi = posrelat(luaL_optint32(L, 2, 1), l);
++  ptrdiff_t pose = posrelat(luaL_optint32(L, 3, posi), l);
+   int n, i;
+   if (posi <= 0) posi = 1;
+   if ((size_t)pose > l) pose = l;
+@@ -496,7 +496,7 @@ static int str_find_aux (lua_State *L, i
+   size_t l1, l2;
+   const char *s = luaL_checklstring(L, 1, &l1);
+   const char *p = luaL_checklstring(L, 2, &l2);
+-  ptrdiff_t init = posrelat(luaL_optinteger(L, 3, 1), l1) - 1;
++  ptrdiff_t init = posrelat(luaL_optint32(L, 3, 1), l1) - 1;
+   if (init < 0) init = 0;
+   else if ((size_t)(init) > l1) init = (ptrdiff_t)l1;
+   if (find && (lua_toboolean(L, 4) ||  /* explicit request? */
+@@ -690,7 +690,7 @@ static int str_gsub (lua_State *L) {
+ ** maximum size of each format specification (such as '%-099.99d')
+ ** (+10 accounts for %99.99x plus margin of error)
+ */
+-#define MAX_FORMAT	(sizeof(FLAGS) + sizeof(LUA_INTFRMLEN) + 10)
++#define MAX_FORMAT	(sizeof(FLAGS) + sizeof(LUA_INTEGER_FMT)-2 + 10)
+ 
+ 
+ static void addquoted (lua_State *L, luaL_Buffer *b, int arg) {
+@@ -747,9 +747,9 @@ static const char *scanformat (lua_State
+ static void addintlen (char *form) {
+   size_t l = strlen(form);
+   char spec = form[l - 1];
+-  strcpy(form + l - 1, LUA_INTFRMLEN);
+-  form[l + sizeof(LUA_INTFRMLEN) - 2] = spec;
+-  form[l + sizeof(LUA_INTFRMLEN) - 1] = '\0';
++  const char *tmp= LUA_INTEGER_FMT;   /* "%lld" or "%ld" */
++  strcpy(form + l - 1, tmp+1);
++  form[l + sizeof(LUA_INTEGER_FMT)-4] = spec;
+ }
+ 
+ 
+@@ -779,12 +779,12 @@ static int str_format (lua_State *L) {
+         }
+         case 'd':  case 'i': {
+           addintlen(form);
+-          sprintf(buff, form, (LUA_INTFRM_T)luaL_checknumber(L, arg));
++          sprintf(buff, form, luaL_checkinteger(L, arg));
+           break;
+         }
+         case 'o':  case 'u':  case 'x':  case 'X': {
+           addintlen(form);
+-          sprintf(buff, form, (unsigned LUA_INTFRM_T)luaL_checknumber(L, arg));
++          sprintf(buff, form, (unsigned LUA_INTEGER)luaL_checkinteger(L, arg));
+           break;
+         }
+         case 'e':  case 'E': case 'f':
+--- a/src/ltable.c
++++ b/src/ltable.c
+@@ -33,6 +33,7 @@
+ #include "lobject.h"
+ #include "lstate.h"
+ #include "ltable.h"
++#include "lnum.h"
+ 
+ 
+ /*
+@@ -51,25 +52,15 @@
+   
+ #define hashstr(t,str)  hashpow2(t, (str)->tsv.hash)
+ #define hashboolean(t,p)        hashpow2(t, p)
+-
++#define hashint(t,i)    hashpow2(t,i)
+ 
+ /*
+ ** for some types, it is better to avoid modulus by power of 2, as
+ ** they tend to have many 2 factors.
+ */
+ #define hashmod(t,n)	(gnode(t, ((n) % ((sizenode(t)-1)|1))))
+-
+-
+ #define hashpointer(t,p)	hashmod(t, IntPoint(p))
+ 
+-
+-/*
+-** number of ints inside a lua_Number
+-*/
+-#define numints		cast_int(sizeof(lua_Number)/sizeof(int))
+-
+-
+-
+ #define dummynode		(&dummynode_)
+ 
+ static const Node dummynode_ = {
+@@ -80,27 +71,46 @@ static const Node dummynode_ = {
+ 
+ /*
+ ** hash for lua_Numbers
++**
++** for non-complex modes, never called with 'lua_Integer' value range (s.a. 0)
+ */
+ static Node *hashnum (const Table *t, lua_Number n) {
+-  unsigned int a[numints];
+-  int i;
+-  if (luai_numeq(n, 0))  /* avoid problems with -0 */
+-    return gnode(t, 0);
+-  memcpy(a, &n, sizeof(a));
+-  for (i = 1; i < numints; i++) a[0] += a[i];
+-  return hashmod(t, a[0]);
++  const unsigned int *p= cast(const unsigned int *,&n);
++  unsigned int sum= *p;
++  unsigned int m= sizeof(lua_Number)/sizeof(int);
++  unsigned int i;
++  /* OS X Intel has 'm'==4 and gives "Bus error" if the last integer of 
++   * 'n' is read; the actual size of long double is only 80 bits = 10 bytes.
++   * Linux x86 has 'm'==3, and does not require reduction.
++   */
++#if defined(LNUM_LDOUBLE) && defined(__i386__)
++  if (m>3) m--;
++#endif
++  for (i = 1; i < m; i++) sum += p[i];
++  return hashmod(t, sum);
+ }
+ 
+ 
+-
+ /*
+ ** returns the `main' position of an element in a table (that is, the index
+ ** of its hash value)
++**
++** Floating point numbers with integer value give the hash position of the
++** integer (so they use the same table position).
+ */
+ static Node *mainposition (const Table *t, const TValue *key) {
++  lua_Integer i;
+   switch (ttype(key)) {
+     case LUA_TNUMBER:
+-      return hashnum(t, nvalue(key));
++      if (tt_integer_valued(key,&i)) 
++        return hashint(t, i);
++#ifdef LNUM_COMPLEX
++      if (nvalue_img_fast(key)!=0 && luai_numeq(nvalue_fast(key),0))
++        return gnode(t, 0);  /* 0 and -0 to give same hash */
++#endif
++      return hashnum(t, nvalue_fast(key));
++    case LUA_TINT:
++      return hashint(t, ivalue(key));
+     case LUA_TSTRING:
+       return hashstr(t, rawtsvalue(key));
+     case LUA_TBOOLEAN:
+@@ -116,16 +126,20 @@ static Node *mainposition (const Table *
+ /*
+ ** returns the index for `key' if `key' is an appropriate key to live in
+ ** the array part of the table, -1 otherwise.
++**
++** Anything <=0 is taken as not being in the array part.
+ */
+-static int arrayindex (const TValue *key) {
+-  if (ttisnumber(key)) {
+-    lua_Number n = nvalue(key);
+-    int k;
+-    lua_number2int(k, n);
+-    if (luai_numeq(cast_num(k), n))
+-      return k;
++static int arrayindex (const TValue *key, int max) {
++  lua_Integer k;
++  switch( ttype(key) ) {
++    case LUA_TINT:
++      k= ivalue(key); break;
++    case LUA_TNUMBER:
++      if (tt_integer_valued(key,&k)) break;
++    default:
++      return -1;  /* not to be used as array index */
+   }
+-  return -1;  /* `key' did not match some condition */
++  return ((k>0) && (k <= max)) ? cast_int(k) : -1;
+ }
+ 
+ 
+@@ -137,8 +151,8 @@ static int arrayindex (const TValue *key
+ static int findindex (lua_State *L, Table *t, StkId key) {
+   int i;
+   if (ttisnil(key)) return -1;  /* first iteration */
+-  i = arrayindex(key);
+-  if (0 < i && i <= t->sizearray)  /* is `key' inside array part? */
++  i = arrayindex(key, t->sizearray);
++  if (i>0)  /* inside array part? */
+     return i-1;  /* yes; that's the index (corrected to C) */
+   else {
+     Node *n = mainposition(t, key);
+@@ -163,7 +177,7 @@ int luaH_next (lua_State *L, Table *t, S
+   int i = findindex(L, t, key);  /* find original element */
+   for (i++; i < t->sizearray; i++) {  /* try first array part */
+     if (!ttisnil(&t->array[i])) {  /* a non-nil value? */
+-      setnvalue(key, cast_num(i+1));
++      setivalue(key, i+1);
+       setobj2s(L, key+1, &t->array[i]);
+       return 1;
+     }
+@@ -209,8 +223,8 @@ static int computesizes (int nums[], int
+ 
+ 
+ static int countint (const TValue *key, int *nums) {
+-  int k = arrayindex(key);
+-  if (0 < k && k <= MAXASIZE) {  /* is `key' an appropriate array index? */
++  int k = arrayindex(key,MAXASIZE);
++  if (k>0) {  /* appropriate array index? */
+     nums[ceillog2(k)]++;  /* count as such */
+     return 1;
+   }
+@@ -308,7 +322,7 @@ static void resize (lua_State *L, Table
+     /* re-insert elements from vanishing slice */
+     for (i=nasize; i<oldasize; i++) {
+       if (!ttisnil(&t->array[i]))
+-        setobjt2t(L, luaH_setnum(L, t, i+1), &t->array[i]);
++        setobjt2t(L, luaH_setint(L, t, i+1), &t->array[i]);
+     }
+     /* shrink array */
+     luaM_reallocvector(L, t->array, oldasize, nasize, TValue);
+@@ -409,7 +423,9 @@ static TValue *newkey (lua_State *L, Tab
+     othern = mainposition(t, key2tval(mp));
+     if (othern != mp) {  /* is colliding node out of its main position? */
+       /* yes; move colliding node into free position */
+-      while (gnext(othern) != mp) othern = gnext(othern);  /* find previous */
++      while (gnext(othern) != mp) {
++        othern = gnext(othern);  /* find previous */
++      }
+       gnext(othern) = n;  /* redo the chain with `n' in place of `mp' */
+       *n = *mp;  /* copy colliding node into free pos. (mp->next also goes) */
+       gnext(mp) = NULL;  /* now `mp' is free */
+@@ -432,17 +448,18 @@ static TValue *newkey (lua_State *L, Tab
+ /*
+ ** search function for integers
+ */
+-const TValue *luaH_getnum (Table *t, int key) {
++const TValue *luaH_getint (Table *t, lua_Integer key) {
+   /* (1 <= key && key <= t->sizearray) */
+   if (cast(unsigned int, key-1) < cast(unsigned int, t->sizearray))
+     return &t->array[key-1];
+   else {
+-    lua_Number nk = cast_num(key);
+-    Node *n = hashnum(t, nk);
++    Node *n = hashint(t, key);
+     do {  /* check whether `key' is somewhere in the chain */
+-      if (ttisnumber(gkey(n)) && luai_numeq(nvalue(gkey(n)), nk))
++      if (ttisint(gkey(n)) && (ivalue(gkey(n)) == key)) {
+         return gval(n);  /* that's it */
+-      else n = gnext(n);
++      } else { 
++      n = gnext(n);
++    }
+     } while (n);
+     return luaO_nilobject;
+   }
+@@ -470,14 +487,12 @@ const TValue *luaH_get (Table *t, const
+   switch (ttype(key)) {
+     case LUA_TNIL: return luaO_nilobject;
+     case LUA_TSTRING: return luaH_getstr(t, rawtsvalue(key));
++    case LUA_TINT: return luaH_getint(t, ivalue(key));
+     case LUA_TNUMBER: {
+-      int k;
+-      lua_Number n = nvalue(key);
+-      lua_number2int(k, n);
+-      if (luai_numeq(cast_num(k), nvalue(key))) /* index is int? */
+-        return luaH_getnum(t, k);  /* use specialized version */
+-      /* else go through */
+-    }
++      lua_Integer i;
++      if (tt_integer_valued(key,&i))
++        return luaH_getint(t,i);
++    } /* pass through */
+     default: {
+       Node *n = mainposition(t, key);
+       do {  /* check whether `key' is somewhere in the chain */
+@@ -498,20 +513,25 @@ TValue *luaH_set (lua_State *L, Table *t
+     return cast(TValue *, p);
+   else {
+     if (ttisnil(key)) luaG_runerror(L, "table index is nil");
+-    else if (ttisnumber(key) && luai_numisnan(nvalue(key)))
+-      luaG_runerror(L, "table index is NaN");
++    else if (ttype(key)==LUA_TNUMBER) {
++      lua_Integer k;
++      if (luai_numisnan(nvalue_fast(key)))
++        luaG_runerror(L, "table index is NaN");
++      if (tt_integer_valued(key,&k))
++        return luaH_setint(L, t, k);
++    }
+     return newkey(L, t, key);
+   }
+ }
+ 
+ 
+-TValue *luaH_setnum (lua_State *L, Table *t, int key) {
+-  const TValue *p = luaH_getnum(t, key);
++TValue *luaH_setint (lua_State *L, Table *t, lua_Integer key) {
++  const TValue *p = luaH_getint(t, key);
+   if (p != luaO_nilobject)
+     return cast(TValue *, p);
+   else {
+     TValue k;
+-    setnvalue(&k, cast_num(key));
++    setivalue(&k, key);
+     return newkey(L, t, &k);
+   }
+ }
+@@ -533,20 +553,21 @@ static int unbound_search (Table *t, uns
+   unsigned int i = j;  /* i is zero or a present index */
+   j++;
+   /* find `i' and `j' such that i is present and j is not */
+-  while (!ttisnil(luaH_getnum(t, j))) {
++  while (!ttisnil(luaH_getint(t, j))) {
+     i = j;
+     j *= 2;
+     if (j > cast(unsigned int, MAX_INT)) {  /* overflow? */
+       /* table was built with bad purposes: resort to linear search */
+-      i = 1;
+-      while (!ttisnil(luaH_getnum(t, i))) i++;
+-      return i - 1;
++      for( i = 1; i<MAX_INT+1; i++ ) {
++        if (ttisnil(luaH_getint(t, i))) break;
++      }
++      return i - 1;  /* up to MAX_INT */
+     }
+   }
+   /* now do a binary search between them */
+   while (j - i > 1) {
+     unsigned int m = (i+j)/2;
+-    if (ttisnil(luaH_getnum(t, m))) j = m;
++    if (ttisnil(luaH_getint(t, m))) j = m;
+     else i = m;
+   }
+   return i;
+--- a/src/ltable.h
++++ b/src/ltable.h
+@@ -18,8 +18,8 @@
+ #define key2tval(n)	(&(n)->i_key.tvk)
+ 
+ 
+-LUAI_FUNC const TValue *luaH_getnum (Table *t, int key);
+-LUAI_FUNC TValue *luaH_setnum (lua_State *L, Table *t, int key);
++LUAI_FUNC const TValue *luaH_getint (Table *t, lua_Integer key);
++LUAI_FUNC TValue *luaH_setint (lua_State *L, Table *t, lua_Integer key);
+ LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key);
+ LUAI_FUNC TValue *luaH_setstr (lua_State *L, Table *t, TString *key);
+ LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key);
+--- a/src/ltm.c
++++ b/src/ltm.c
+@@ -19,7 +19,6 @@
+ #include "ltm.h"
+ 
+ 
+-
+ const char *const luaT_typenames[] = {
+   "nil", "boolean", "userdata", "number",
+   "string", "table", "function", "userdata", "thread",
+@@ -67,6 +66,9 @@ const TValue *luaT_gettmbyobj (lua_State
+     case LUA_TUSERDATA:
+       mt = uvalue(o)->metatable;
+       break;
++    case LUA_TINT:
++      mt = G(L)->mt[LUA_TNUMBER];
++      break;
+     default:
+       mt = G(L)->mt[ttype(o)];
+   }
+--- a/src/lua.c
++++ b/src/lua.c
+@@ -16,7 +16,7 @@
+ 
+ #include "lauxlib.h"
+ #include "lualib.h"
+-
++#include "llimits.h"
+ 
+ 
+ static lua_State *globalL = NULL;
+@@ -382,6 +382,15 @@ int main (int argc, char **argv) {
+     l_message(argv[0], "cannot create state: not enough memory");
+     return EXIT_FAILURE;
+   }
++  /* Checking 'sizeof(lua_Integer)' cannot be made in preprocessor on all compilers.
++  */
++#ifdef LNUM_INT16
++  lua_assert( sizeof(lua_Integer) == 2 );
++#elif defined(LNUM_INT32)
++  lua_assert( sizeof(lua_Integer) == 4 );
++#elif defined(LNUM_INT64)
++  lua_assert( sizeof(lua_Integer) == 8 );
++#endif
+   s.argc = argc;
+   s.argv = argv;
+   status = lua_cpcall(L, &pmain, &s);
+--- a/src/lua.h
++++ b/src/lua.h
+@@ -19,7 +19,7 @@
+ #define LUA_VERSION	"Lua 5.1"
+ #define LUA_RELEASE	"Lua 5.1.5"
+ #define LUA_VERSION_NUM	501
+-#define LUA_COPYRIGHT	"Copyright (C) 1994-2012 Lua.org, PUC-Rio"
++#define LUA_COPYRIGHT	"Copyright (C) 1994-2012 Lua.org, PUC-Rio" " (" LUA_LNUM ")"
+ #define LUA_AUTHORS 	"R. Ierusalimschy, L. H. de Figueiredo & W. Celes"
+ 
+ 
+@@ -71,6 +71,16 @@ typedef void * (*lua_Alloc) (void *ud, v
+ */
+ #define LUA_TNONE		(-1)
+ 
++/* LUA_TINT is an internal type, not visible to applications. There are three
++ * potential values where it can be tweaked to (code autoadjusts to these):
++ *
++ * -2: not 'usual' type value; good since 'LUA_TINT' is not part of the API
++ * LUA_TNUMBER+1: shifts other type values upwards, breaking binary compatibility
++ *     not acceptable for 5.1, maybe 5.2 onwards?
++ *  9: greater than existing (5.1) type values.
++*/
++#define LUA_TINT (-2)
++
+ #define LUA_TNIL		0
+ #define LUA_TBOOLEAN		1
+ #define LUA_TLIGHTUSERDATA	2
+@@ -139,6 +149,8 @@ LUA_API int             (lua_isuserdata)
+ LUA_API int             (lua_type) (lua_State *L, int idx);
+ LUA_API const char     *(lua_typename) (lua_State *L, int tp);
+ 
++LUA_API int             (lua_isinteger) (lua_State *L, int idx);
++
+ LUA_API int            (lua_equal) (lua_State *L, int idx1, int idx2);
+ LUA_API int            (lua_rawequal) (lua_State *L, int idx1, int idx2);
+ LUA_API int            (lua_lessthan) (lua_State *L, int idx1, int idx2);
+@@ -244,6 +256,19 @@ LUA_API lua_Alloc (lua_getallocf) (lua_S
+ LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud);
+ 
+ 
++/*
++* It is unnecessary to break Lua C API 'lua_tonumber()' compatibility, just
++* because the Lua number type is complex. Most C modules would use scalars
++* only. We'll introduce new 'lua_tocomplex' and 'lua_pushcomplex' for when
++* the module really wants to use them.
++*/
++#ifdef LNUM_COMPLEX
++  #include <complex.h>
++  typedef LUA_NUMBER complex lua_Complex;
++  LUA_API lua_Complex (lua_tocomplex) (lua_State *L, int idx);
++  LUA_API void (lua_pushcomplex) (lua_State *L, lua_Complex v);
++#endif
++
+ 
+ /* 
+ ** ===============================================================
+@@ -268,7 +293,12 @@ LUA_API void lua_setallocf (lua_State *L
+ #define lua_isboolean(L,n)	(lua_type(L, (n)) == LUA_TBOOLEAN)
+ #define lua_isthread(L,n)	(lua_type(L, (n)) == LUA_TTHREAD)
+ #define lua_isnone(L,n)		(lua_type(L, (n)) == LUA_TNONE)
+-#define lua_isnoneornil(L, n)	(lua_type(L, (n)) <= 0)
++
++#if LUA_TINT < 0
++# define lua_isnoneornil(L, n)	( (lua_type(L,(n)) <= 0) && (lua_type(L,(n)) != LUA_TINT) )
++#else
++# define lua_isnoneornil(L, n)	(lua_type(L, (n)) <= 0)
++#endif
+ 
+ #define lua_pushliteral(L, s)	\
+ 	lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1)
+@@ -386,3 +416,4 @@ struct lua_Debug {
+ 
+ 
+ #endif
++
+--- a/src/luaconf.h
++++ b/src/luaconf.h
+@@ -10,7 +10,9 @@
+ 
+ #include <limits.h>
+ #include <stddef.h>
+-
++#ifdef lua_assert
++# include <assert.h>
++#endif
+ 
+ /*
+ ** ==================================================================
+@@ -136,14 +138,38 @@
+ 
+ 
+ /*
+-@@ LUA_INTEGER is the integral type used by lua_pushinteger/lua_tointeger.
+-** CHANGE that if ptrdiff_t is not adequate on your machine. (On most
+-** machines, ptrdiff_t gives a good choice between int or long.)
++@@ LUAI_BITSINT defines the number of bits in an int.
++** CHANGE here if Lua cannot automatically detect the number of bits of
++** your machine. Probably you do not need to change this.
+ */
+-#define LUA_INTEGER	ptrdiff_t
++/* avoid overflows in comparison */
++#if INT_MAX-20 < 32760
++#define LUAI_BITSINT	16
++#elif INT_MAX > 2147483640L
++/* int has at least 32 bits */
++#define LUAI_BITSINT	32
++#else
++#error "you must define LUA_BITSINT with number of bits in an integer"
++#endif
+ 
+ 
+ /*
++@@ LNUM_DOUBLE | LNUM_FLOAT | LNUM_LDOUBLE: Generic Lua number mode
++@@ LNUM_INT32 | LNUM_INT64: Integer type
++@@ LNUM_COMPLEX: Define for using 'a+bi' numbers
++@@
++@@ You can combine LNUM_xxx but only one of each group. I.e. '-DLNUM_FLOAT
++@@ -DLNUM_INT32 -DLNUM_COMPLEX' gives float range complex numbers, with 
++@@ 32-bit scalar integer range optimized.
++**
++** These are kept in a separate configuration file mainly for ease of patching
++** (can be changed if integerated to Lua proper).
++*/
++/*#define LNUM_DOUBLE*/
++/*#define LNUM_INT32*/
++#include "lnum_config.h"
++
++/*
+ @@ LUA_API is a mark for all core API functions.
+ @@ LUALIB_API is a mark for all standard library functions.
+ ** CHANGE them if you need to define those functions in some special way.
+@@ -383,22 +409,6 @@
+ 
+ 
+ /*
+-@@ LUAI_BITSINT defines the number of bits in an int.
+-** CHANGE here if Lua cannot automatically detect the number of bits of
+-** your machine. Probably you do not need to change this.
+-*/
+-/* avoid overflows in comparison */
+-#if INT_MAX-20 < 32760
+-#define LUAI_BITSINT	16
+-#elif INT_MAX > 2147483640L
+-/* int has at least 32 bits */
+-#define LUAI_BITSINT	32
+-#else
+-#error "you must define LUA_BITSINT with number of bits in an integer"
+-#endif
+-
+-
+-/*
+ @@ LUAI_UINT32 is an unsigned integer with at least 32 bits.
+ @@ LUAI_INT32 is an signed integer with at least 32 bits.
+ @@ LUAI_UMEM is an unsigned integer big enough to count the total
+@@ -425,6 +435,15 @@
+ #define LUAI_MEM	long
+ #endif
+ 
++/*
++@@ LUAI_BOOL carries 0 and nonzero (normally 1). It may be defined as 'char'
++** (to save memory), 'int' (for speed), 'bool' (for C++) or '_Bool' (C99)
++*/
++#ifdef __cplusplus
++# define LUAI_BOOL bool
++#else
++# define LUAI_BOOL int
++#endif
+ 
+ /*
+ @@ LUAI_MAXCALLS limits the number of nested calls.
+@@ -490,101 +509,6 @@
+ /* }================================================================== */
+ 
+ 
+-
+-
+-/*
+-** {==================================================================
+-@@ LUA_NUMBER is the type of numbers in Lua.
+-** CHANGE the following definitions only if you want to build Lua
+-** with a number type different from double. You may also need to
+-** change lua_number2int & lua_number2integer.
+-** ===================================================================
+-*/
+-
+-#define LUA_NUMBER_DOUBLE
+-#define LUA_NUMBER	double
+-
+-/*
+-@@ LUAI_UACNUMBER is the result of an 'usual argument conversion'
+-@* over a number.
+-*/
+-#define LUAI_UACNUMBER	double
+-
+-
+-/*
+-@@ LUA_NUMBER_SCAN is the format for reading numbers.
+-@@ LUA_NUMBER_FMT is the format for writing numbers.
+-@@ lua_number2str converts a number to a string.
+-@@ LUAI_MAXNUMBER2STR is maximum size of previous conversion.
+-@@ lua_str2number converts a string to a number.
+-*/
+-#define LUA_NUMBER_SCAN		"%lf"
+-#define LUA_NUMBER_FMT		"%.14g"
+-#define lua_number2str(s,n)	sprintf((s), LUA_NUMBER_FMT, (n))
+-#define LUAI_MAXNUMBER2STR	32 /* 16 digits, sign, point, and \0 */
+-#define lua_str2number(s,p)	strtod((s), (p))
+-
+-
+-/*
+-@@ The luai_num* macros define the primitive operations over numbers.
+-*/
+-#if defined(LUA_CORE)
+-#include <math.h>
+-#define luai_numadd(a,b)	((a)+(b))
+-#define luai_numsub(a,b)	((a)-(b))
+-#define luai_nummul(a,b)	((a)*(b))
+-#define luai_numdiv(a,b)	((a)/(b))
+-#define luai_nummod(a,b)	((a) - floor((a)/(b))*(b))
+-#define luai_numpow(a,b)	(pow(a,b))
+-#define luai_numunm(a)		(-(a))
+-#define luai_numeq(a,b)		((a)==(b))
+-#define luai_numlt(a,b)		((a)<(b))
+-#define luai_numle(a,b)		((a)<=(b))
+-#define luai_numisnan(a)	(!luai_numeq((a), (a)))
+-#endif
+-
+-
+-/*
+-@@ lua_number2int is a macro to convert lua_Number to int.
+-@@ lua_number2integer is a macro to convert lua_Number to lua_Integer.
+-** CHANGE them if you know a faster way to convert a lua_Number to
+-** int (with any rounding method and without throwing errors) in your
+-** system. In Pentium machines, a naive typecast from double to int
+-** in C is extremely slow, so any alternative is worth trying.
+-*/
+-
+-/* On a Pentium, resort to a trick */
+-#if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) && !defined(__SSE2__) && \
+-    (defined(__i386) || defined (_M_IX86) || defined(__i386__))
+-
+-/* On a Microsoft compiler, use assembler */
+-#if defined(_MSC_VER)
+-
+-#define lua_number2int(i,d)   __asm fld d   __asm fistp i
+-#define lua_number2integer(i,n)		lua_number2int(i, n)
+-
+-/* the next trick should work on any Pentium, but sometimes clashes
+-   with a DirectX idiosyncrasy */
+-#else
+-
+-union luai_Cast { double l_d; long l_l; };
+-#define lua_number2int(i,d) \
+-  { volatile union luai_Cast u; u.l_d = (d) + 6755399441055744.0; (i) = u.l_l; }
+-#define lua_number2integer(i,n)		lua_number2int(i, n)
+-
+-#endif
+-
+-
+-/* this option always works, but may be slow */
+-#else
+-#define lua_number2int(i,d)	((i)=(int)(d))
+-#define lua_number2integer(i,d)	((i)=(lua_Integer)(d))
+-
+-#endif
+-
+-/* }================================================================== */
+-
+-
+ /*
+ @@ LUAI_USER_ALIGNMENT_T is a type that requires maximum alignment.
+ ** CHANGE it if your system requires alignments larger than double. (For
+@@ -728,28 +652,6 @@ union luai_Cast { double l_d; long l_l;
+ #define luai_userstateyield(L,n)	((void)L)
+ 
+ 
+-/*
+-@@ LUA_INTFRMLEN is the length modifier for integer conversions
+-@* in 'string.format'.
+-@@ LUA_INTFRM_T is the integer type correspoding to the previous length
+-@* modifier.
+-** CHANGE them if your system supports long long or does not support long.
+-*/
+-
+-#if defined(LUA_USELONGLONG)
+-
+-#define LUA_INTFRMLEN		"ll"
+-#define LUA_INTFRM_T		long long
+-
+-#else
+-
+-#define LUA_INTFRMLEN		"l"
+-#define LUA_INTFRM_T		long
+-
+-#endif
+-
+-
+-
+ /* =================================================================== */
+ 
+ /*
+--- a/src/lundump.c
++++ b/src/lundump.c
+@@ -73,6 +73,13 @@ static lua_Number LoadNumber(LoadState*
+  return x;
+ }
+ 
++static lua_Integer LoadInteger(LoadState* S)
++{
++ lua_Integer x;
++ LoadVar(S,x);
++ return x;
++}
++
+ static TString* LoadString(LoadState* S)
+ {
+  size_t size;
+@@ -119,6 +126,9 @@ static void LoadConstants(LoadState* S,
+    case LUA_TNUMBER:
+ 	setnvalue(o,LoadNumber(S));
+ 	break;
++   case LUA_TINT:   /* Integer type saved in bytecode (see lcode.c) */
++	setivalue(o,LoadInteger(S));
++	break;
+    case LUA_TSTRING:
+ 	setsvalue2n(S->L,o,LoadString(S));
+ 	break;
+@@ -223,5 +233,22 @@ void luaU_header (char* h)
+  *h++=(char)sizeof(size_t);
+  *h++=(char)sizeof(Instruction);
+  *h++=(char)sizeof(lua_Number);
+- *h++=(char)(((lua_Number)0.5)==0);		/* is lua_Number integral? */
++
++ /* 
++  * Last byte of header (0/1 in unpatched Lua 5.1.3):
++  *
++  * 0: lua_Number is float or double, lua_Integer not used. (nonpatched only)
++  * 1: lua_Number is integer (nonpatched only)
++  *
++  * +2: LNUM_INT16: sizeof(lua_Integer)
++  * +4: LNUM_INT32: sizeof(lua_Integer)
++  * +8: LNUM_INT64: sizeof(lua_Integer)
++  *
++  * +0x80: LNUM_COMPLEX
++  */
++ *h++ = (char)(sizeof(lua_Integer)
++#ifdef LNUM_COMPLEX
++    | 0x80
++#endif
++    );
+ }
+--- a/src/lvm.c
++++ b/src/lvm.c
+@@ -25,22 +25,35 @@
+ #include "ltable.h"
+ #include "ltm.h"
+ #include "lvm.h"
+-
+-
++#include "llex.h"
++#include "lnum.h"
+ 
+ /* limit for table tag-method chains (to avoid loops) */
+ #define MAXTAGLOOP	100
+ 
+ 
+-const TValue *luaV_tonumber (const TValue *obj, TValue *n) {
+-  lua_Number num;
++/*
++ * If 'obj' is a string, it is tried to be interpreted as a number.
++ */
++const TValue *luaV_tonumber ( const TValue *obj, TValue *n) {
++  lua_Number d;
++  lua_Integer i;
++  
+   if (ttisnumber(obj)) return obj;
+-  if (ttisstring(obj) && luaO_str2d(svalue(obj), &num)) {
+-    setnvalue(n, num);
+-    return n;
+-  }
+-  else
+-    return NULL;
++
++  if (ttisstring(obj)) {
++    switch( luaO_str2d( svalue(obj), &d, &i ) ) {
++        case TK_INT:
++            setivalue(n,i); return n;
++        case TK_NUMBER: 
++            setnvalue(n,d); return n;
++#ifdef LNUM_COMPLEX
++        case TK_NUMBER2:    /* "N.NNNi", != 0 */
++            setnvalue_complex_fast(n, d*I); return n;
++#endif
++        }
++    }
++  return NULL;
+ }
+ 
+ 
+@@ -49,8 +62,7 @@ int luaV_tostring (lua_State *L, StkId o
+     return 0;
+   else {
+     char s[LUAI_MAXNUMBER2STR];
+-    lua_Number n = nvalue(obj);
+-    lua_number2str(s, n);
++    luaO_num2buf(s,obj);
+     setsvalue2s(L, obj, luaS_new(L, s));
+     return 1;
+   }
+@@ -222,59 +234,127 @@ static int l_strcmp (const TString *ls,
+ }
+ 
+ 
++#ifdef LNUM_COMPLEX
++void error_complex( lua_State *L, const TValue *l, const TValue *r )
++{
++  char buf1[ LUAI_MAXNUMBER2STR ];
++  char buf2[ LUAI_MAXNUMBER2STR ];
++  luaO_num2buf( buf1, l );
++  luaO_num2buf( buf2, r );
++  luaG_runerror( L, "unable to compare: %s with %s", buf1, buf2 );
++  /* no return */
++}
++#endif
++
++
+ int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) {
+   int res;
+-  if (ttype(l) != ttype(r))
++  int tl,tr;
++  lua_Integer tmp;
++
++  if (!ttype_ext_same(l,r))
+     return luaG_ordererror(L, l, r);
+-  else if (ttisnumber(l))
+-    return luai_numlt(nvalue(l), nvalue(r));
+-  else if (ttisstring(l))
+-    return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0;
+-  else if ((res = call_orderTM(L, l, r, TM_LT)) != -1)
++#ifdef LNUM_COMPLEX
++  if ( (nvalue_img(l)!=0) || (nvalue_img(r)!=0) )
++    error_complex( L, l, r );
++#endif
++  tl= ttype(l); tr= ttype(r);
++  if (tl==tr) {  /* clear arithmetics */
++    switch(tl) {
++      case LUA_TINT:      return ivalue(l) < ivalue(r);
++      case LUA_TNUMBER:   return luai_numlt(nvalue_fast(l), nvalue_fast(r));
++      case LUA_TSTRING:   return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0;
++    }
++  } else if (tl==LUA_TINT) {  /* l:int, r:num */
++    /* Avoid accuracy losing casts: if 'r' is integer by value, do comparisons
++     * in integer realm. Only otherwise cast 'l' to FP (which might change its
++     * value).
++     */
++    if (tt_integer_valued(r,&tmp)) 
++        return ivalue(l) < tmp;
++    else 
++        return luai_numlt( cast_num(ivalue(l)), nvalue_fast(r) );
++
++  } else if (tl==LUA_TNUMBER) {  /* l:num, r:int */
++    if (tt_integer_valued(l,&tmp)) 
++        return tmp < ivalue(r);
++    else
++        return luai_numlt( nvalue_fast(l), cast_num(ivalue(r)) );
++
++  } else if ((res = call_orderTM(L, l, r, TM_LT)) != -1)
+     return res;
++
+   return luaG_ordererror(L, l, r);
+ }
+ 
+ 
+ static int lessequal (lua_State *L, const TValue *l, const TValue *r) {
+   int res;
+-  if (ttype(l) != ttype(r))
++  int tl, tr;
++  lua_Integer tmp;
++
++  if (!ttype_ext_same(l,r))
+     return luaG_ordererror(L, l, r);
+-  else if (ttisnumber(l))
+-    return luai_numle(nvalue(l), nvalue(r));
+-  else if (ttisstring(l))
+-    return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0;
+-  else if ((res = call_orderTM(L, l, r, TM_LE)) != -1)  /* first try `le' */
++#ifdef LNUM_COMPLEX
++  if ( (nvalue_img(l)!=0) || (nvalue_img(r)!=0) )
++    error_complex( L, l, r );
++#endif
++  tl= ttype(l); tr= ttype(r);
++  if (tl==tr) {  /* clear arithmetics */
++    switch(tl) {
++      case LUA_TINT:      return ivalue(l) <= ivalue(r);
++      case LUA_TNUMBER:   return luai_numle(nvalue_fast(l), nvalue_fast(r));
++      case LUA_TSTRING:   return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0;
++    }
++  }
++  if (tl==LUA_TINT) {  /* l:int, r:num */
++    if (tt_integer_valued(r,&tmp)) 
++        return ivalue(l) <= tmp;
++    else
++        return luai_numle( cast_num(ivalue(l)), nvalue_fast(r) );
++
++  } else if (tl==LUA_TNUMBER) {  /* l:num, r:int */
++    if (tt_integer_valued(l,&tmp)) 
++        return tmp <= ivalue(r);
++    else
++        return luai_numle( nvalue_fast(l), cast_num(ivalue(r)) );
++
++  } else if ((res = call_orderTM(L, l, r, TM_LE)) != -1)  /* first try `le' */
+     return res;
+   else if ((res = call_orderTM(L, r, l, TM_LT)) != -1)  /* else try `lt' */
+     return !res;
++
+   return luaG_ordererror(L, l, r);
+ }
+ 
+ 
+-int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2) {
++/* Note: 'luaV_equalval()' and 'luaO_rawequalObj()' have largely overlapping
++ *       implementation. LUA_TNIL..LUA_TLIGHTUSERDATA cases could be handled
++ *       simply by the 'default' case here.
++ */
++int luaV_equalval (lua_State *L, const TValue *l, const TValue *r) {
+   const TValue *tm;
+-  lua_assert(ttype(t1) == ttype(t2));
+-  switch (ttype(t1)) {
++  lua_assert(ttype_ext_same(l,r));
++  switch (ttype(l)) {
+     case LUA_TNIL: return 1;
+-    case LUA_TNUMBER: return luai_numeq(nvalue(t1), nvalue(t2));
+-    case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2);  /* true must be 1 !! */
+-    case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2);
++    case LUA_TINT:
++    case LUA_TNUMBER: return luaO_rawequalObj(l,r);
++    case LUA_TBOOLEAN: return bvalue(l) == bvalue(r);  /* true must be 1 !! */
++    case LUA_TLIGHTUSERDATA: return pvalue(l) == pvalue(r);
+     case LUA_TUSERDATA: {
+-      if (uvalue(t1) == uvalue(t2)) return 1;
+-      tm = get_compTM(L, uvalue(t1)->metatable, uvalue(t2)->metatable,
+-                         TM_EQ);
++      if (uvalue(l) == uvalue(r)) return 1;
++      tm = get_compTM(L, uvalue(l)->metatable, uvalue(r)->metatable, TM_EQ);
+       break;  /* will try TM */
+     }
+     case LUA_TTABLE: {
+-      if (hvalue(t1) == hvalue(t2)) return 1;
+-      tm = get_compTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable, TM_EQ);
++      if (hvalue(l) == hvalue(r)) return 1;
++      tm = get_compTM(L, hvalue(l)->metatable, hvalue(r)->metatable, TM_EQ);
+       break;  /* will try TM */
+     }
+-    default: return gcvalue(t1) == gcvalue(t2);
++    default: return gcvalue(l) == gcvalue(r);
+   }
+   if (tm == NULL) return 0;  /* no TM? */
+-  callTMres(L, L->top, tm, t1, t2);  /* call TM */
++  callTMres(L, L->top, tm, l, r);  /* call TM */
+   return !l_isfalse(L->top);
+ }
+ 
+@@ -314,30 +394,6 @@ void luaV_concat (lua_State *L, int tota
+ }
+ 
+ 
+-static void Arith (lua_State *L, StkId ra, const TValue *rb,
+-                   const TValue *rc, TMS op) {
+-  TValue tempb, tempc;
+-  const TValue *b, *c;
+-  if ((b = luaV_tonumber(rb, &tempb)) != NULL &&
+-      (c = luaV_tonumber(rc, &tempc)) != NULL) {
+-    lua_Number nb = nvalue(b), nc = nvalue(c);
+-    switch (op) {
+-      case TM_ADD: setnvalue(ra, luai_numadd(nb, nc)); break;
+-      case TM_SUB: setnvalue(ra, luai_numsub(nb, nc)); break;
+-      case TM_MUL: setnvalue(ra, luai_nummul(nb, nc)); break;
+-      case TM_DIV: setnvalue(ra, luai_numdiv(nb, nc)); break;
+-      case TM_MOD: setnvalue(ra, luai_nummod(nb, nc)); break;
+-      case TM_POW: setnvalue(ra, luai_numpow(nb, nc)); break;
+-      case TM_UNM: setnvalue(ra, luai_numunm(nb)); break;
+-      default: lua_assert(0); break;
+-    }
+-  }
+-  else if (!call_binTM(L, rb, rc, ra, op))
+-    luaG_aritherror(L, rb, rc);
+-}
+-
+-
+-
+ /*
+ ** some macros for common tasks in `luaV_execute'
+ */
+@@ -361,17 +417,154 @@ static void Arith (lua_State *L, StkId r
+ #define Protect(x)	{ L->savedpc = pc; {x;}; base = L->base; }
+ 
+ 
+-#define arith_op(op,tm) { \
+-        TValue *rb = RKB(i); \
+-        TValue *rc = RKC(i); \
+-        if (ttisnumber(rb) && ttisnumber(rc)) { \
+-          lua_Number nb = nvalue(rb), nc = nvalue(rc); \
+-          setnvalue(ra, op(nb, nc)); \
+-        } \
+-        else \
+-          Protect(Arith(L, ra, rb, rc, tm)); \
++/* Note: if called for unary operations, 'rc'=='rb'.
++ */
++static void Arith (lua_State *L, StkId ra, const TValue *rb,
++                   const TValue *rc, TMS op) {
++  TValue tempb, tempc;
++  const TValue *b, *c;
++  lua_Number nb,nc;
++
++  if ((b = luaV_tonumber(rb, &tempb)) != NULL &&
++      (c = luaV_tonumber(rc, &tempc)) != NULL) {
++
++    /* Keep integer arithmetics in the integer realm, if possible.
++     */
++    if (ttisint(b) && ttisint(c)) {
++      lua_Integer ib = ivalue(b), ic = ivalue(c);
++      lua_Integer *ri = &ra->value.i;
++      ra->tt= LUA_TINT;  /* part of 'setivalue(ra)' */
++      switch (op) {
++        case TM_ADD: if (try_addint( ri, ib, ic)) return; break;
++        case TM_SUB: if (try_subint( ri, ib, ic)) return; break;
++        case TM_MUL: if (try_mulint( ri, ib, ic)) return; break;
++        case TM_DIV: if (try_divint( ri, ib, ic)) return; break;
++        case TM_MOD: if (try_modint( ri, ib, ic)) return; break;
++        case TM_POW: if (try_powint( ri, ib, ic)) return; break;
++        case TM_UNM: if (try_unmint( ri, ib)) return; break;
++        default: lua_assert(0);
+       }
++    }
++    /* Fallback to floating point, when leaving range. */
+ 
++#ifdef LNUM_COMPLEX
++    if ((nvalue_img(b)!=0) || (nvalue_img(c)!=0)) {
++      lua_Complex r;
++      if (op==TM_UNM) {
++        r= -nvalue_complex_fast(b);     /* never an integer (or scalar) */
++        setnvalue_complex_fast( ra, r );
++      } else {
++        lua_Complex bb= nvalue_complex(b), cc= nvalue_complex(c);
++        switch (op) {
++          case TM_ADD: r= bb + cc; break;
++          case TM_SUB: r= bb - cc; break;
++          case TM_MUL: r= bb * cc; break;
++          case TM_DIV: r= bb / cc; break;
++          case TM_MOD: 
++            luaG_runerror(L, "attempt to use %% on complex numbers");  /* no return */
++          case TM_POW: r= luai_vectpow( bb, cc ); break;
++          default: lua_assert(0); r=0;
++        }
++        setnvalue_complex( ra, r );
++      }
++      return;
++    }
++#endif
++    nb = nvalue(b); nc = nvalue(c);
++    switch (op) {
++      case TM_ADD: setnvalue(ra, luai_numadd(nb, nc)); return;
++      case TM_SUB: setnvalue(ra, luai_numsub(nb, nc)); return;
++      case TM_MUL: setnvalue(ra, luai_nummul(nb, nc)); return;
++      case TM_DIV: setnvalue(ra, luai_numdiv(nb, nc)); return;
++      case TM_MOD: setnvalue(ra, luai_nummod(nb, nc)); return;
++      case TM_POW: setnvalue(ra, luai_numpow(nb, nc)); return;
++      case TM_UNM: setnvalue(ra, luai_numunm(nb)); return;
++      default: lua_assert(0);
++    }
++  }
++  
++  /* Either operand not a number */
++  if (!call_binTM(L, rb, rc, ra, op))
++    luaG_aritherror(L, rb, rc);
++}
++
++/* Helper macro to sort arithmetic operations into four categories:
++ *  TK_INT: integer - integer operands
++ *  TK_NUMBER: number - number (non complex, either may be integer)
++ *  TK_NUMBER2: complex numbers (at least the other)
++ *  0: non-numeric (at least the other)
++*/
++#ifdef LNUM_COMPLEX
++static inline int arith_mode( const TValue *rb, const TValue *rc ) {
++  if (ttisint(rb) && ttisint(rc)) return TK_INT;
++  if (ttiscomplex(rb) || ttiscomplex(rc)) return TK_NUMBER2;
++  if (ttisnumber(rb) && ttisnumber(rc)) return TK_NUMBER;
++  return 0;
++}
++#else
++# define arith_mode(rb,rc) \
++    ( (ttisint(rb) && ttisint(rc)) ? TK_INT : \
++      (ttisnumber(rb) && ttisnumber(rc)) ? TK_NUMBER : 0 )
++#endif
++
++/* arith_op macro for two operators:
++ * automatically chooses, which function (number, integer, complex) to use
++ */
++#define ARITH_OP2_START( op_num, op_int ) \
++  int failed= 0; \
++  switch( arith_mode(rb,rc) ) { \
++    case TK_INT: \
++      if (op_int ( &(ra)->value.i, ivalue(rb), ivalue(rc) )) \
++        { ra->tt= LUA_TINT; break; } /* else flow through */ \
++    case TK_NUMBER: \
++      setnvalue(ra, op_num ( nvalue(rb), nvalue(rc) )); break;
++
++#define ARITH_OP2_END \
++    default: \
++      failed= 1; break; \
++  } if (!failed) continue;
++
++#define arith_op_continue_scalar( op_num, op_int ) \
++    ARITH_OP2_START( op_num, op_int ) \
++    ARITH_OP2_END
++
++#ifdef LNUM_COMPLEX
++# define arith_op_continue( op_num, op_int, op_complex ) \
++    ARITH_OP2_START( op_num, op_int ) \
++      case TK_NUMBER2: \
++        setnvalue_complex( ra, op_complex ( nvalue_complex(rb), nvalue_complex(rc) ) ); break; \
++    ARITH_OP2_END
++#else
++# define arith_op_continue(op_num,op_int,_) arith_op_continue_scalar(op_num,op_int)
++#endif
++
++/* arith_op macro for one operator:
++ */
++#define ARITH_OP1_START( op_num, op_int ) \
++  int failed= 0; \
++  switch( arith_mode(rb,rb) ) { \
++    case TK_INT: \
++      if (op_int ( &(ra)->value.i, ivalue(rb) )) \
++        { ra->tt= LUA_TINT; break; } /* else flow through */ \
++      case TK_NUMBER: \
++        setnvalue(ra, op_num (nvalue(rb))); break; \
++
++#define ARITH_OP1_END \
++      default: \
++        failed= 1; break; \
++  } if (!failed) continue;
++
++#ifdef LNUM_COMPLEX
++# define arith_op1_continue( op_num, op_int, op_complex ) \
++    ARITH_OP1_START( op_num, op_int ) \
++      case TK_NUMBER2: \
++        setnvalue_complex( ra, op_complex ( nvalue_complex_fast(rb) )); break; \
++    ARITH_OP1_END
++#else
++# define arith_op1_continue( op_num, op_int, _ ) \
++    ARITH_OP1_START( op_num, op_int ) \
++    ARITH_OP1_END
++#endif
+ 
+ 
+ void luaV_execute (lua_State *L, int nexeccalls) {
+@@ -472,38 +665,45 @@ void luaV_execute (lua_State *L, int nex
+         continue;
+       }
+       case OP_ADD: {
+-        arith_op(luai_numadd, TM_ADD);
++        TValue *rb = RKB(i), *rc= RKC(i);
++        arith_op_continue( luai_numadd, try_addint, luai_vectadd );
++        Protect(Arith(L, ra, rb, rc, TM_ADD)); \
+         continue;
+       }
+       case OP_SUB: {
+-        arith_op(luai_numsub, TM_SUB);
++        TValue *rb = RKB(i), *rc= RKC(i);
++        arith_op_continue( luai_numsub, try_subint, luai_vectsub );
++        Protect(Arith(L, ra, rb, rc, TM_SUB));
+         continue;
+       }
+       case OP_MUL: {
+-        arith_op(luai_nummul, TM_MUL);
++        TValue *rb = RKB(i), *rc= RKC(i);
++        arith_op_continue(luai_nummul, try_mulint, luai_vectmul);
++        Protect(Arith(L, ra, rb, rc, TM_MUL));
+         continue;
+       }
+       case OP_DIV: {
+-        arith_op(luai_numdiv, TM_DIV);
++        TValue *rb = RKB(i), *rc= RKC(i);
++        arith_op_continue(luai_numdiv, try_divint, luai_vectdiv);
++        Protect(Arith(L, ra, rb, rc, TM_DIV));
+         continue;
+       }
+       case OP_MOD: {
+-        arith_op(luai_nummod, TM_MOD);
++        TValue *rb = RKB(i), *rc= RKC(i);
++        arith_op_continue_scalar(luai_nummod, try_modint);  /* scalars only */
++        Protect(Arith(L, ra, rb, rc, TM_MOD));
+         continue;
+       }
+       case OP_POW: {
+-        arith_op(luai_numpow, TM_POW);
++        TValue *rb = RKB(i), *rc= RKC(i);
++        arith_op_continue(luai_numpow, try_powint, luai_vectpow);
++        Protect(Arith(L, ra, rb, rc, TM_POW));
+         continue;
+       }
+       case OP_UNM: {
+         TValue *rb = RB(i);
+-        if (ttisnumber(rb)) {
+-          lua_Number nb = nvalue(rb);
+-          setnvalue(ra, luai_numunm(nb));
+-        }
+-        else {
+-          Protect(Arith(L, ra, rb, rb, TM_UNM));
+-        }
++        arith_op1_continue(luai_numunm, try_unmint, luai_vectunm);
++        Protect(Arith(L, ra, rb, rb, TM_UNM));
+         continue;
+       }
+       case OP_NOT: {
+@@ -515,11 +715,11 @@ void luaV_execute (lua_State *L, int nex
+         const TValue *rb = RB(i);
+         switch (ttype(rb)) {
+           case LUA_TTABLE: {
+-            setnvalue(ra, cast_num(luaH_getn(hvalue(rb))));
++            setivalue(ra, luaH_getn(hvalue(rb)));
+             break;
+           }
+           case LUA_TSTRING: {
+-            setnvalue(ra, cast_num(tsvalue(rb)->len));
++            setivalue(ra, tsvalue(rb)->len);
+             break;
+           }
+           default: {  /* try metamethod */
+@@ -652,14 +852,30 @@ void luaV_execute (lua_State *L, int nex
+         }
+       }
+       case OP_FORLOOP: {
+-        lua_Number step = nvalue(ra+2);
+-        lua_Number idx = luai_numadd(nvalue(ra), step); /* increment index */
+-        lua_Number limit = nvalue(ra+1);
+-        if (luai_numlt(0, step) ? luai_numle(idx, limit)
+-                                : luai_numle(limit, idx)) {
+-          dojump(L, pc, GETARG_sBx(i));  /* jump back */
+-          setnvalue(ra, idx);  /* update internal index... */
+-          setnvalue(ra+3, idx);  /* ...and external index */
++        /* If start,step and limit are all integers, we don't need to check
++         * against overflow in the looping.
++         */
++        if (ttisint(ra) && ttisint(ra+1) && ttisint(ra+2)) {
++          lua_Integer step = ivalue(ra+2);
++          lua_Integer idx = ivalue(ra) + step; /* increment index */
++          lua_Integer limit = ivalue(ra+1);
++          if (step > 0 ? (idx <= limit) : (limit <= idx)) {
++            dojump(L, pc, GETARG_sBx(i));  /* jump back */
++            setivalue(ra, idx);  /* update internal index... */
++            setivalue(ra+3, idx);  /* ...and external index */
++          }
++        } else {
++          /* non-integer looping (don't use 'nvalue_fast', some may be integer!) 
++          */
++          lua_Number step = nvalue(ra+2);
++          lua_Number idx = luai_numadd(nvalue(ra), step); /* increment index */
++          lua_Number limit = nvalue(ra+1);
++          if (luai_numlt(0, step) ? luai_numle(idx, limit)
++                                  : luai_numle(limit, idx)) {
++            dojump(L, pc, GETARG_sBx(i));  /* jump back */
++            setnvalue(ra, idx);  /* update internal index... */
++            setnvalue(ra+3, idx);  /* ...and external index */
++          }
+         }
+         continue;
+       }
+@@ -668,13 +884,21 @@ void luaV_execute (lua_State *L, int nex
+         const TValue *plimit = ra+1;
+         const TValue *pstep = ra+2;
+         L->savedpc = pc;  /* next steps may throw errors */
++        /* Using same location for tonumber's both arguments, effectively does
++         * in-place modification (string->number). */
+         if (!tonumber(init, ra))
+           luaG_runerror(L, LUA_QL("for") " initial value must be a number");
+         else if (!tonumber(plimit, ra+1))
+           luaG_runerror(L, LUA_QL("for") " limit must be a number");
+         else if (!tonumber(pstep, ra+2))
+           luaG_runerror(L, LUA_QL("for") " step must be a number");
+-        setnvalue(ra, luai_numsub(nvalue(ra), nvalue(pstep)));
++        /* Step back one value (keep within integers if we can)
++         */
++        if (!( ttisint(ra) && ttisint(pstep) &&
++               try_subint( &ra->value.i, ivalue(ra), ivalue(pstep) ) )) {
++            /* don't use 'nvalue_fast()', values may be integer */
++            setnvalue(ra, luai_numsub(nvalue(ra), nvalue(pstep)));
++        }
+         dojump(L, pc, GETARG_sBx(i));
+         continue;
+       }
+@@ -711,7 +935,7 @@ void luaV_execute (lua_State *L, int nex
+           luaH_resizearray(L, h, last);  /* pre-alloc it at once */
+         for (; n > 0; n--) {
+           TValue *val = ra+n;
+-          setobj2t(L, luaH_setnum(L, h, last--), val);
++          setobj2t(L, luaH_setint(L, h, last--), val);
+           luaC_barriert(L, h, val);
+         }
+         continue;
+--- a/src/lvm.h
++++ b/src/lvm.h
+@@ -15,11 +15,9 @@
+ 
+ #define tostring(L,o) ((ttype(o) == LUA_TSTRING) || (luaV_tostring(L, o)))
+ 
+-#define tonumber(o,n)	(ttype(o) == LUA_TNUMBER || \
+-                         (((o) = luaV_tonumber(o,n)) != NULL))
++#define tonumber(o,n) (ttisnumber(o) || (((o) = luaV_tonumber(o,n)) != NULL))
+ 
+-#define equalobj(L,o1,o2) \
+-	(ttype(o1) == ttype(o2) && luaV_equalval(L, o1, o2))
++#define equalobj(L,o1,o2) (ttype_ext_same(o1,o2) && luaV_equalval(L, o1, o2))
+ 
+ 
+ LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r);
+--- a/src/print.c
++++ b/src/print.c
+@@ -14,6 +14,7 @@
+ #include "lobject.h"
+ #include "lopcodes.h"
+ #include "lundump.h"
++#include "lnum.h"
+ 
+ #define PrintFunction	luaU_print
+ 
+@@ -59,8 +60,16 @@ static void PrintConstant(const Proto* f
+   case LUA_TBOOLEAN:
+ 	printf(bvalue(o) ? "true" : "false");
+ 	break;
++  case LUA_TINT:
++	printf(LUA_INTEGER_FMT,ivalue(o));
++	break;
+   case LUA_TNUMBER:
+-	printf(LUA_NUMBER_FMT,nvalue(o));
++#ifdef LNUM_COMPLEX
++    // TBD: Do we get complex values here?
++    { lua_Number b= nvalue_img_fast(o);
++	  printf( LUA_NUMBER_FMT "%s" LUA_NUMBER_FMT "i", nvalue_fast(o), b>=0 ? "+":"", b ); }
++#endif
++	printf(LUA_NUMBER_FMT,nvalue_fast(o));
+ 	break;
+   case LUA_TSTRING:
+ 	PrintString(rawtsvalue(o));
diff --git a/package/utils/lua/patches-host/011-lnum-use-double.patch b/package/utils/lua/patches-host/011-lnum-use-double.patch
new file mode 100644
index 0000000..14c720b
--- /dev/null
+++ b/package/utils/lua/patches-host/011-lnum-use-double.patch
@@ -0,0 +1,11 @@
+--- a/src/lnum_config.h
++++ b/src/lnum_config.h
+@@ -11,7 +11,7 @@
+ ** Default number modes
+ */
+ #if (!defined LNUM_DOUBLE) && (!defined LNUM_FLOAT) && (!defined LNUM_LDOUBLE)
+-# define LNUM_FLOAT
++# define LNUM_DOUBLE
+ #endif
+ #if (!defined LNUM_INT16) && (!defined LNUM_INT32) && (!defined LNUM_INT64)
+ # define LNUM_INT32
diff --git a/package/utils/lua/patches-host/012-lnum-fix-ltle-relational-operators.patch b/package/utils/lua/patches-host/012-lnum-fix-ltle-relational-operators.patch
new file mode 100644
index 0000000..3d3d685
--- /dev/null
+++ b/package/utils/lua/patches-host/012-lnum-fix-ltle-relational-operators.patch
@@ -0,0 +1,22 @@
+--- a/src/lvm.c
++++ b/src/lvm.c
+@@ -281,7 +281,8 @@ int luaV_lessthan (lua_State *L, const T
+     else
+         return luai_numlt( nvalue_fast(l), cast_num(ivalue(r)) );
+ 
+-  } else if ((res = call_orderTM(L, l, r, TM_LT)) != -1)
++  } 
++  if ((res = call_orderTM(L, l, r, TM_LT)) != -1)
+     return res;
+ 
+   return luaG_ordererror(L, l, r);
+@@ -319,7 +320,8 @@ static int lessequal (lua_State *L, cons
+     else
+         return luai_numle( nvalue_fast(l), cast_num(ivalue(r)) );
+ 
+-  } else if ((res = call_orderTM(L, l, r, TM_LE)) != -1)  /* first try `le' */
++  } 
++  if ((res = call_orderTM(L, l, r, TM_LE)) != -1)  /* first try `le' */
+     return res;
+   else if ((res = call_orderTM(L, r, l, TM_LT)) != -1)  /* else try `lt' */
+     return !res;
diff --git a/package/utils/lua/patches-host/013-lnum-strtoul-parsing-fixes.patch b/package/utils/lua/patches-host/013-lnum-strtoul-parsing-fixes.patch
new file mode 100644
index 0000000..8887229
--- /dev/null
+++ b/package/utils/lua/patches-host/013-lnum-strtoul-parsing-fixes.patch
@@ -0,0 +1,41 @@
+--- a/src/lnum.c
++++ b/src/lnum.c
+@@ -127,6 +127,8 @@ static int luaO_str2i (const char *s, lu
+ #else
+       return 0;  /* Reject the number */
+ #endif
++    } else if (v > LUA_INTEGER_MAX) {
++      return TK_NUMBER;
+     }
+   } else if ((v > LUA_INTEGER_MAX) || (*endptr && (!isspace(*endptr)))) {
+     return TK_NUMBER;	/* not in signed range, or has '.', 'e' etc. trailing */
+@@ -310,3 +312,13 @@ int try_unmint( lua_Integer *r, lua_Inte
+   return 0;
+ }
+ 
++#ifdef LONG_OVERFLOW_LUA_INTEGER
++unsigned LUA_INTEGER lua_str2ul( const char *str, char **endptr, int base ) {
++  unsigned long v= strtoul(str, endptr, base);
++  if ( v > LUA_INTEGER_MAX ) {
++    errno= ERANGE;
++    v= ULONG_MAX;
++  }
++  return (unsigned LUA_INTEGER)v;
++}
++#endif
+--- a/src/lnum_config.h
++++ b/src/lnum_config.h
+@@ -141,7 +141,12 @@
+ #endif
+ 
+ #ifndef lua_str2ul
+-# define lua_str2ul (unsigned LUA_INTEGER)strtoul
++# if LONG_MAX > LUA_INTEGER_MAX
++#   define LONG_OVERFLOW_LUA_INTEGER
++    unsigned LUA_INTEGER lua_str2ul( const char *str, char **endptr, int base );
++# else
++#  define lua_str2ul (unsigned LUA_INTEGER)strtoul
++# endif
+ #endif
+ #ifndef LUA_INTEGER_MIN
+ # define LUA_INTEGER_MIN (-LUA_INTEGER_MAX -1)  /* -2^16|32 */
diff --git a/package/utils/lua/patches-host/015-lnum-ppc-compat.patch b/package/utils/lua/patches-host/015-lnum-ppc-compat.patch
new file mode 100644
index 0000000..2ea59f1
--- /dev/null
+++ b/package/utils/lua/patches-host/015-lnum-ppc-compat.patch
@@ -0,0 +1,11 @@
+--- a/src/lua.h
++++ b/src/lua.h
+@@ -79,7 +79,7 @@ typedef void * (*lua_Alloc) (void *ud, v
+  *     not acceptable for 5.1, maybe 5.2 onwards?
+  *  9: greater than existing (5.1) type values.
+ */
+-#define LUA_TINT (-2)
++#define LUA_TINT 9
+ 
+ #define LUA_TNIL		0
+ #define LUA_TBOOLEAN		1
diff --git a/package/utils/lua/patches-host/030-archindependent-bytecode.patch b/package/utils/lua/patches-host/030-archindependent-bytecode.patch
new file mode 100644
index 0000000..8dfef85
--- /dev/null
+++ b/package/utils/lua/patches-host/030-archindependent-bytecode.patch
@@ -0,0 +1,111 @@
+--- a/src/ldump.c
++++ b/src/ldump.c
+@@ -67,12 +67,12 @@ static void DumpString(const TString* s,
+ {
+  if (s==NULL || getstr(s)==NULL)
+  {
+-  size_t size=0;
++  unsigned int size=0;
+   DumpVar(size,D);
+  }
+  else
+  {
+-  size_t size=s->tsv.len+1;		/* include trailing '\0' */
++  unsigned int size=s->tsv.len+1;		/* include trailing '\0' */
+   DumpVar(size,D);
+   DumpBlock(getstr(s),size,D);
+  }
+--- a/src/lundump.c
++++ b/src/lundump.c
+@@ -25,6 +25,7 @@ typedef struct {
+  ZIO* Z;
+  Mbuffer* b;
+  const char* name;
++ int swap;
+ } LoadState;
+ 
+ #ifdef LUAC_TRUST_BINARIES
+@@ -40,7 +41,6 @@ static void error(LoadState* S, const ch
+ }
+ #endif
+ 
+-#define LoadMem(S,b,n,size)	LoadBlock(S,b,(n)*(size))
+ #define	LoadByte(S)		(lu_byte)LoadChar(S)
+ #define LoadVar(S,x)		LoadMem(S,&x,1,sizeof(x))
+ #define LoadVector(S,b,n,size)	LoadMem(S,b,n,size)
+@@ -51,6 +51,49 @@ static void LoadBlock(LoadState* S, void
+  IF (r!=0, "unexpected end");
+ }
+ 
++static void LoadMem (LoadState* S, void* b, int n, size_t size)
++{
++ LoadBlock(S,b,n*size);
++ if (S->swap)
++ {
++  char* p=(char*) b;
++  char c;
++  switch (size)
++  {
++   case 1:
++  	break;
++   case 2:
++	while (n--)
++	{
++	 c=p[0]; p[0]=p[1]; p[1]=c;
++	 p+=2;
++	}
++  	break;
++   case 4:
++	while (n--)
++	{
++	 c=p[0]; p[0]=p[3]; p[3]=c;
++	 c=p[1]; p[1]=p[2]; p[2]=c;
++	 p+=4;
++	}
++  	break;
++   case 8:
++	while (n--)
++	{
++	 c=p[0]; p[0]=p[7]; p[7]=c;
++	 c=p[1]; p[1]=p[6]; p[6]=c;
++	 c=p[2]; p[2]=p[5]; p[5]=c;
++	 c=p[3]; p[3]=p[4]; p[4]=c;
++	 p+=8;
++	}
++  	break;
++   default:
++   	IF(1, "bad size");
++  	break;
++  }
++ }
++}
++
+ static int LoadChar(LoadState* S)
+ {
+  char x;
+@@ -82,7 +125,7 @@ static lua_Integer LoadInteger(LoadState
+ 
+ static TString* LoadString(LoadState* S)
+ {
+- size_t size;
++ unsigned int size;
+  LoadVar(S,size);
+  if (size==0)
+   return NULL;
+@@ -196,6 +239,7 @@ static void LoadHeader(LoadState* S)
+  char s[LUAC_HEADERSIZE];
+  luaU_header(h);
+  LoadBlock(S,s,LUAC_HEADERSIZE);
++ S->swap=(s[6]!=h[6]); s[6]=h[6];
+  IF (memcmp(h,s,LUAC_HEADERSIZE)!=0, "bad header");
+ }
+ 
+@@ -230,7 +274,7 @@ void luaU_header (char* h)
+  *h++=(char)LUAC_FORMAT;
+  *h++=(char)*(char*)&x;				/* endianness */
+  *h++=(char)sizeof(int);
+- *h++=(char)sizeof(size_t);
++ *h++=(char)sizeof(unsigned int);
+  *h++=(char)sizeof(Instruction);
+  *h++=(char)sizeof(lua_Number);
+ 
diff --git a/package/utils/lua/patches-host/100-no_readline.patch b/package/utils/lua/patches-host/100-no_readline.patch
new file mode 100644
index 0000000..700114e
--- /dev/null
+++ b/package/utils/lua/patches-host/100-no_readline.patch
@@ -0,0 +1,49 @@
+--- a/src/luaconf.h
++++ b/src/luaconf.h
+@@ -38,7 +38,6 @@
+ #if defined(LUA_USE_LINUX)
+ #define LUA_USE_POSIX
+ #define LUA_USE_DLOPEN		/* needs an extra library: -ldl */
+-#define LUA_USE_READLINE	/* needs some extra libraries */
+ #endif
+ 
+ #if defined(LUA_USE_MACOSX)
+--- a/src/Makefile
++++ b/src/Makefile
+@@ -17,6 +17,7 @@ LIBS= -lm $(MYLIBS)
+ MYCFLAGS=
+ MYLDFLAGS=
+ MYLIBS=
++# USE_READLINE=1
+ 
+ # == END OF USER SETTINGS. NO NEED TO CHANGE ANYTHING BELOW THIS LINE =========
+ 
+@@ -75,7 +76,7 @@ echo:
+ 	@echo "MYLIBS = $(MYLIBS)"
+ 
+ # convenience targets for popular platforms
+-
++RFLAG=$(if $(USE_READLINE),-DLUA_USE_READLINE)
+ none:
+ 	@echo "Please choose a platform:"
+ 	@echo "   $(PLATS)"
+@@ -90,16 +91,16 @@ bsd:
+ 	$(MAKE) all MYCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN" MYLIBS="-Wl,-E"
+ 
+ freebsd:
+-	$(MAKE) all MYCFLAGS="-DLUA_USE_LINUX" MYLIBS="-Wl,-E -lreadline"
++	$(MAKE) all MYCFLAGS="-DLUA_USE_LINUX" $(RFLAG)" MYLIBS="-Wl,-E$(if $(USE_READLINE), -lreadline)"
+ 
+ generic:
+ 	$(MAKE) all MYCFLAGS=
+ 
+ linux:
+-	$(MAKE) all MYCFLAGS=-DLUA_USE_LINUX MYLIBS="-Wl,-E -ldl -lreadline -lhistory -lncurses"
++	$(MAKE) all MYCFLAGS="-DLUA_USE_LINUX $(RFLAG)" MYLIBS="-Wl,-E -ldl $(if $(USE_READLINE), -lreadline -lhistory -lncurses)"
+ 
+ macosx:
+-	$(MAKE) all MYCFLAGS=-DLUA_USE_LINUX MYLIBS="-lreadline"
++	$(MAKE) all MYCFLAGS=-DLUA_USE_LINUX $(if $(USE_READLINE), MYLIBS="-lreadline")
+ # use this on Mac OS X 10.3-
+ #	$(MAKE) all MYCFLAGS=-DLUA_USE_MACOSX
+ 
diff --git a/package/utils/lua/patches-host/400-CVE-2014-5461.patch b/package/utils/lua/patches-host/400-CVE-2014-5461.patch
new file mode 100644
index 0000000..cce73ff
--- /dev/null
+++ b/package/utils/lua/patches-host/400-CVE-2014-5461.patch
@@ -0,0 +1,19 @@
+From: Enrico Tassi <gareuselesinge@debian.org>
+Date: Tue, 26 Aug 2014 16:20:55 +0200
+Subject: Fix stack overflow in vararg functions
+
+---
+ src/ldo.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/src/ldo.c
++++ b/src/ldo.c
+@@ -274,7 +274,7 @@ int luaD_precall (lua_State *L, StkId fu
+     CallInfo *ci;
+     StkId st, base;
+     Proto *p = cl->p;
+-    luaD_checkstack(L, p->maxstacksize);
++    luaD_checkstack(L, p->maxstacksize + p->numparams);
+     func = restorestack(L, funcr);
+     if (!p->is_vararg) {  /* no varargs? */
+       base = func + 1;
diff --git a/package/utils/lua/patches/001-include-version-number.patch b/package/utils/lua/patches/001-include-version-number.patch
new file mode 100644
index 0000000..806d370
--- /dev/null
+++ b/package/utils/lua/patches/001-include-version-number.patch
@@ -0,0 +1,56 @@
+From 96576b44a1b368bd6590eb0778ae45cc9ccede3f Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
+Date: Fri, 21 Jun 2019 14:08:38 +0200
+Subject: [PATCH] include version number
+
+Including it allows multiple lua versions to coexist.
+
+Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
+---
+
+--- a/Makefile
++++ b/Makefile
+@@ -41,10 +41,10 @@ RANLIB= ranlib
+ PLATS= aix ansi bsd freebsd generic linux macosx mingw posix solaris
+ 
+ # What to install.
+-TO_BIN= lua luac
++TO_BIN= lua$V luac$V
+ TO_INC= lua.h luaconf.h lualib.h lauxlib.h ../etc/lua.hpp
+ TO_LIB= liblua.a
+-TO_MAN= lua.1 luac.1
++TO_MAN= lua$V.1 luac$V.1
+ 
+ # Lua version and release.
+ V= 5.1
+@@ -53,7 +53,7 @@ R= 5.1.5
+ all:	$(PLAT)
+ 
+ $(PLATS) clean:
+-	cd src && $(MAKE) $@
++	cd src && $(MAKE) $@ V=$V
+ 
+ test:	dummy
+ 	src/lua test/hello.lua
+diff --git a/doc/lua.1 b/doc/lua5.1.1
+rename from doc/lua.1
+rename to doc/lua5.1.1
+diff --git a/doc/luac.1 b/doc/luac5.1.1
+rename from doc/luac.1
+rename to doc/luac5.1.1
+diff --git a/src/Makefile b/src/Makefile
+--- a/src/Makefile
++++ b/src/Makefile
+@@ -29,10 +29,10 @@ CORE_O=	lapi.o lcode.o ldebug.o ldo.o ld
+ LIB_O=	lauxlib.o lbaselib.o ldblib.o liolib.o lmathlib.o loslib.o ltablib.o \
+ 	lstrlib.o loadlib.o linit.o
+ 
+-LUA_T=	lua
++LUA_T=	lua$V
+ LUA_O=	lua.o
+ 
+-LUAC_T=	luac
++LUAC_T=	luac$V
+ LUAC_O=	luac.o print.o
+ 
+ ALL_O= $(CORE_O) $(LIB_O) $(LUA_O) $(LUAC_O)
diff --git a/package/utils/lua/patches/010-lua-5.1.3-lnum-full-260308.patch b/package/utils/lua/patches/010-lua-5.1.3-lnum-full-260308.patch
new file mode 100644
index 0000000..58cc894
--- /dev/null
+++ b/package/utils/lua/patches/010-lua-5.1.3-lnum-full-260308.patch
@@ -0,0 +1,3737 @@
+--- a/src/Makefile
++++ b/src/Makefile
+@@ -25,7 +25,7 @@ PLATS= aix ansi bsd freebsd generic linu
+ LUA_A=	liblua.a
+ CORE_O=	lapi.o lcode.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o lmem.o \
+ 	lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o ltm.o  \
+-	lundump.o lvm.o lzio.o
++	lundump.o lvm.o lzio.o lnum.o
+ LIB_O=	lauxlib.o lbaselib.o ldblib.o liolib.o lmathlib.o loslib.o ltablib.o \
+ 	lstrlib.o loadlib.o linit.o
+ 
+@@ -148,6 +148,7 @@ llex.o: llex.c lua.h luaconf.h ldo.h lob
+ lmathlib.o: lmathlib.c lua.h luaconf.h lauxlib.h lualib.h
+ lmem.o: lmem.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \
+   ltm.h lzio.h lmem.h ldo.h
++lnum.o: lnum.c lua.h llex.h lnum.h
+ loadlib.o: loadlib.c lua.h luaconf.h lauxlib.h lualib.h
+ lobject.o: lobject.c lua.h luaconf.h ldo.h lobject.h llimits.h lstate.h \
+   ltm.h lzio.h lmem.h lstring.h lgc.h lvm.h
+@@ -179,4 +180,18 @@ lzio.o: lzio.c lua.h luaconf.h llimits.h
+ print.o: print.c ldebug.h lstate.h lua.h luaconf.h lobject.h llimits.h \
+   ltm.h lzio.h lmem.h lopcodes.h lundump.h
+ 
++luaconf.h: lnum_config.h
++lapi.c: lnum.h
++lauxlib.c: llimits.h
++lbaselib.c: llimits.h lobject.h lapi.h
++lcode.c: lnum.h
++liolib.c: lnum.h llex.h
++llex.c: lnum.h
++lnum.h: lobject.h
++lobject.c: llex.h lnum.h
++ltable.c: lnum.h
++lua.c: llimits.h
++lvm.c: llex.h lnum.h
++print.c: lnum.h
++
+ # (end of Makefile)
+--- a/src/lapi.c
++++ b/src/lapi.c
+@@ -28,7 +28,7 @@
+ #include "ltm.h"
+ #include "lundump.h"
+ #include "lvm.h"
+-
++#include "lnum.h"
+ 
+ 
+ const char lua_ident[] =
+@@ -241,12 +241,13 @@ LUA_API void lua_pushvalue (lua_State *L
+ 
+ LUA_API int lua_type (lua_State *L, int idx) {
+   StkId o = index2adr(L, idx);
+-  return (o == luaO_nilobject) ? LUA_TNONE : ttype(o);
++  return (o == luaO_nilobject) ? LUA_TNONE : ttype_ext(o);
+ }
+ 
+ 
+ LUA_API const char *lua_typename (lua_State *L, int t) {
+   UNUSED(L);
++  lua_assert( t!= LUA_TINT );
+   return (t == LUA_TNONE) ? "no value" : luaT_typenames[t];
+ }
+ 
+@@ -264,6 +265,14 @@ LUA_API int lua_isnumber (lua_State *L,
+ }
+ 
+ 
++LUA_API int lua_isinteger (lua_State *L, int idx) {
++  TValue tmp;
++  lua_Integer dum;
++  const TValue *o = index2adr(L, idx);
++  return tonumber(o,&tmp) && (ttisint(o) || tt_integer_valued(o,&dum));
++}
++
++
+ LUA_API int lua_isstring (lua_State *L, int idx) {
+   int t = lua_type(L, idx);
+   return (t == LUA_TSTRING || t == LUA_TNUMBER);
+@@ -309,31 +318,66 @@ LUA_API int lua_lessthan (lua_State *L,
+ }
+ 
+ 
+-
+ LUA_API lua_Number lua_tonumber (lua_State *L, int idx) {
+   TValue n;
+   const TValue *o = index2adr(L, idx);
+-  if (tonumber(o, &n))
++  if (tonumber(o, &n)) {
++#ifdef LNUM_COMPLEX
++    if (nvalue_img(o) != 0)
++      luaG_runerror(L, "expecting a real number");
++#endif
+     return nvalue(o);
+-  else
+-    return 0;
++  }
++  return 0;
+ }
+ 
+ 
+ LUA_API lua_Integer lua_tointeger (lua_State *L, int idx) {
+   TValue n;
++    /* Lua 5.1 documented behaviour is to return nonzero for non-integer:
++     * "If the number is not an integer, it is truncated in some non-specified way." 
++     * I would suggest to change this, to return 0 for anything that would
++     * not fit in 'lua_Integer'.
++     */
++#ifdef LUA_COMPAT_TOINTEGER
++  /* Lua 5.1 compatible */
+   const TValue *o = index2adr(L, idx);
+   if (tonumber(o, &n)) {
+-    lua_Integer res;
+-    lua_Number num = nvalue(o);
+-    lua_number2integer(res, num);
+-    return res;
++    lua_Integer i;
++    lua_Number d;
++    if (ttisint(o)) return ivalue(o);
++    d= nvalue_fast(o);
++# ifdef LNUM_COMPLEX
++    if (nvalue_img_fast(o) != 0)
++      luaG_runerror(L, "expecting a real number");
++# endif
++    lua_number2integer(i, d);
++    return i;
+   }
+-  else
+-    return 0;
++#else
++  /* New suggestion */
++  const TValue *o = index2adr(L, idx);
++  if (tonumber(o, &n)) {
++    lua_Integer i;
++    if (ttisint(o)) return ivalue(o);
++    if (tt_integer_valued(o,&i)) return i;
++  }
++#endif
++  return 0;
+ }
+ 
+ 
++#ifdef LNUM_COMPLEX
++LUA_API lua_Complex lua_tocomplex (lua_State *L, int idx) {
++  TValue tmp;
++  const TValue *o = index2adr(L, idx);
++  if (tonumber(o, &tmp))
++    return nvalue_complex(o);
++  return 0;
++}
++#endif
++
++
+ LUA_API int lua_toboolean (lua_State *L, int idx) {
+   const TValue *o = index2adr(L, idx);
+   return !l_isfalse(o);
+@@ -364,6 +408,7 @@ LUA_API size_t lua_objlen (lua_State *L,
+     case LUA_TSTRING: return tsvalue(o)->len;
+     case LUA_TUSERDATA: return uvalue(o)->len;
+     case LUA_TTABLE: return luaH_getn(hvalue(o));
++    case LUA_TINT:
+     case LUA_TNUMBER: {
+       size_t l;
+       lua_lock(L);  /* `luaV_tostring' may create a new string */
+@@ -426,6 +471,8 @@ LUA_API void lua_pushnil (lua_State *L)
+ }
+ 
+ 
++/* 'lua_pushnumber()' may lose accuracy on integers, 'lua_pushinteger' will not.
++ */
+ LUA_API void lua_pushnumber (lua_State *L, lua_Number n) {
+   lua_lock(L);
+   setnvalue(L->top, n);
+@@ -434,12 +481,22 @@ LUA_API void lua_pushnumber (lua_State *
+ }
+ 
+ 
+-LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) {
++LUA_API void lua_pushinteger (lua_State *L, lua_Integer i) {
++  lua_lock(L);
++  setivalue(L->top, i);
++  api_incr_top(L);
++  lua_unlock(L);
++}
++
++
++#ifdef LNUM_COMPLEX
++LUA_API void lua_pushcomplex (lua_State *L, lua_Complex v) {
+   lua_lock(L);
+-  setnvalue(L->top, cast_num(n));
++  setnvalue_complex( L->top, v );
+   api_incr_top(L);
+   lua_unlock(L);
+ }
++#endif
+ 
+ 
+ LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len) {
+@@ -569,7 +626,7 @@ LUA_API void lua_rawgeti (lua_State *L,
+   lua_lock(L);
+   o = index2adr(L, idx);
+   api_check(L, ttistable(o));
+-  setobj2s(L, L->top, luaH_getnum(hvalue(o), n));
++  setobj2s(L, L->top, luaH_getint(hvalue(o), n));
+   api_incr_top(L);
+   lua_unlock(L);
+ }
+@@ -597,6 +654,9 @@ LUA_API int lua_getmetatable (lua_State
+     case LUA_TUSERDATA:
+       mt = uvalue(obj)->metatable;
+       break;
++    case LUA_TINT:
++      mt = G(L)->mt[LUA_TNUMBER];
++      break;
+     default:
+       mt = G(L)->mt[ttype(obj)];
+       break;
+@@ -687,7 +747,7 @@ LUA_API void lua_rawseti (lua_State *L,
+   api_checknelems(L, 1);
+   o = index2adr(L, idx);
+   api_check(L, ttistable(o));
+-  setobj2t(L, luaH_setnum(L, hvalue(o), n), L->top-1);
++  setobj2t(L, luaH_setint(L, hvalue(o), n), L->top-1);
+   luaC_barriert(L, hvalue(o), L->top-1);
+   L->top--;
+   lua_unlock(L);
+@@ -721,7 +781,7 @@ LUA_API int lua_setmetatable (lua_State
+       break;
+     }
+     default: {
+-      G(L)->mt[ttype(obj)] = mt;
++      G(L)->mt[ttype_ext(obj)] = mt;
+       break;
+     }
+   }
+@@ -1085,3 +1145,32 @@ LUA_API const char *lua_setupvalue (lua_
+   return name;
+ }
+ 
++
++/* Help function for 'luaB_tonumber()', avoids multiple str->number
++ * conversions for Lua "tonumber()".
++ *
++ * Also pushes floating point numbers with integer value as integer, which
++ * can be used by 'tonumber()' in scripts to bring values back to integer
++ * realm.
++ *
++ * Note: The 'back to integer realm' is _not_ to affect string conversions:
++ * 'tonumber("4294967295.1")' should give a floating point value, although
++ * the value would be 4294967296 (and storable in int64 realm).
++ */
++int lua_pushvalue_as_number (lua_State *L, int idx)
++{
++  const TValue *o = index2adr(L, idx);
++  TValue tmp;
++  lua_Integer i;
++  if (ttisnumber(o)) {
++    if ( (!ttisint(o)) && tt_integer_valued(o,&i)) {
++      lua_pushinteger( L, i );
++      return 1;
++    }
++  } else if (!tonumber(o, &tmp)) {
++    return 0;
++  }
++  if (ttisint(o)) lua_pushinteger( L, ivalue(o) );
++  else lua_pushnumber( L, nvalue_fast(o) );
++  return 1;
++}
+--- a/src/lapi.h
++++ b/src/lapi.h
+@@ -13,4 +13,6 @@
+ 
+ LUAI_FUNC void luaA_pushobject (lua_State *L, const TValue *o);
+ 
++int lua_pushvalue_as_number (lua_State *L, int idx);
++
+ #endif
+--- a/src/lauxlib.c
++++ b/src/lauxlib.c
+@@ -23,7 +23,7 @@
+ #include "lua.h"
+ 
+ #include "lauxlib.h"
+-
++#include "llimits.h"
+ 
+ #define FREELIST_REF	0	/* free list of references */
+ 
+@@ -66,7 +66,7 @@ LUALIB_API int luaL_typerror (lua_State
+ 
+ 
+ static void tag_error (lua_State *L, int narg, int tag) {
+-  luaL_typerror(L, narg, lua_typename(L, tag));
++  luaL_typerror(L, narg, tag==LUA_TINT ? "integer" : lua_typename(L, tag));
+ }
+ 
+ 
+@@ -188,8 +188,8 @@ LUALIB_API lua_Number luaL_optnumber (lu
+ 
+ LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int narg) {
+   lua_Integer d = lua_tointeger(L, narg);
+-  if (d == 0 && !lua_isnumber(L, narg))  /* avoid extra test when d is not 0 */
+-    tag_error(L, narg, LUA_TNUMBER);
++  if (d == 0 && !lua_isinteger(L, narg))  /* avoid extra test when d is not 0 */
++    tag_error(L, narg, LUA_TINT);
+   return d;
+ }
+ 
+@@ -200,6 +200,16 @@ LUALIB_API lua_Integer luaL_optinteger (
+ }
+ 
+ 
++#ifdef LNUM_COMPLEX
++LUALIB_API lua_Complex luaL_checkcomplex (lua_State *L, int narg) {
++  lua_Complex c = lua_tocomplex(L, narg);
++  if (c == 0 && !lua_isnumber(L, narg))  /* avoid extra test when c is not 0 */
++    tag_error(L, narg, LUA_TNUMBER);
++  return c;
++}
++#endif
++
++
+ LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) {
+   if (!lua_getmetatable(L, obj))  /* no metatable? */
+     return 0;
+--- a/src/lauxlib.h
++++ b/src/lauxlib.h
+@@ -57,6 +57,12 @@ LUALIB_API lua_Number (luaL_optnumber) (
+ LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int numArg);
+ LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg,
+                                           lua_Integer def);
++#define luaL_checkint32(L,narg) ((int)luaL_checkinteger(L,narg))
++#define luaL_optint32(L,narg,def) ((int)luaL_optinteger(L,narg,def))
++
++#ifdef LNUM_COMPLEX
++  LUALIB_API lua_Complex (luaL_checkcomplex) (lua_State *L, int narg);
++#endif
+ 
+ LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg);
+ LUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t);
+--- a/src/lbaselib.c
++++ b/src/lbaselib.c
+@@ -18,7 +18,9 @@
+ 
+ #include "lauxlib.h"
+ #include "lualib.h"
+-
++#include "llimits.h"
++#include "lobject.h"
++#include "lapi.h"
+ 
+ 
+ 
+@@ -54,20 +56,25 @@ static int luaB_tonumber (lua_State *L)
+   int base = luaL_optint(L, 2, 10);
+   if (base == 10) {  /* standard conversion */
+     luaL_checkany(L, 1);
+-    if (lua_isnumber(L, 1)) {
+-      lua_pushnumber(L, lua_tonumber(L, 1));
++    if (lua_isnumber(L, 1)) {       /* numeric string, or a number */
++      lua_pushvalue_as_number(L,1);     /* API extension (not to lose accuracy here) */
+       return 1;
+-    }
++	}
+   }
+   else {
+     const char *s1 = luaL_checkstring(L, 1);
+     char *s2;
+-    unsigned long n;
++    unsigned LUA_INTEGER n;
+     luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range");
+-    n = strtoul(s1, &s2, base);
++    n = lua_str2ul(s1, &s2, base);
+     if (s1 != s2) {  /* at least one valid digit? */
+       while (isspace((unsigned char)(*s2))) s2++;  /* skip trailing spaces */
+       if (*s2 == '\0') {  /* no invalid trailing characters? */
++	  
++		/* Push as number, there needs to be separate 'luaB_tointeger' for
++		 * when the caller wants to preserve the bits (matters if unsigned
++		 * values are used).
++		 */
+         lua_pushnumber(L, (lua_Number)n);
+         return 1;
+       }
+@@ -144,7 +151,7 @@ static int luaB_setfenv (lua_State *L) {
+   luaL_checktype(L, 2, LUA_TTABLE);
+   getfunc(L, 0);
+   lua_pushvalue(L, 2);
+-  if (lua_isnumber(L, 1) && lua_tonumber(L, 1) == 0) {
++  if (lua_isnumber(L, 1) && lua_tointeger(L, 1) == 0) {
+     /* change environment of current thread */
+     lua_pushthread(L);
+     lua_insert(L, -2);
+@@ -209,7 +216,7 @@ static int luaB_collectgarbage (lua_Stat
+       return 1;
+     }
+     default: {
+-      lua_pushnumber(L, res);
++      lua_pushinteger(L, res);
+       return 1;
+     }
+   }
+@@ -631,6 +638,8 @@ static void base_open (lua_State *L) {
+   luaL_register(L, "_G", base_funcs);
+   lua_pushliteral(L, LUA_VERSION);
+   lua_setglobal(L, "_VERSION");  /* set global _VERSION */
++  lua_pushliteral(L, LUA_LNUM);
++  lua_setglobal(L, "_LNUM");  /* "[complex] double|float|ldouble int32|int64" */
+   /* `ipairs' and `pairs' need auxiliary functions as upvalues */
+   auxopen(L, "ipairs", luaB_ipairs, ipairsaux);
+   auxopen(L, "pairs", luaB_pairs, luaB_next);
+--- a/src/lcode.c
++++ b/src/lcode.c
+@@ -22,13 +22,18 @@
+ #include "lopcodes.h"
+ #include "lparser.h"
+ #include "ltable.h"
++#include "lnum.h"
+ 
+ 
+ #define hasjumps(e)	((e)->t != (e)->f)
+ 
+-
+ static int isnumeral(expdesc *e) {
+-  return (e->k == VKNUM && e->t == NO_JUMP && e->f == NO_JUMP);
++  int ek=
++#ifdef LNUM_COMPLEX
++    (e->k == VKNUM2) ||
++#endif
++    (e->k == VKINT) || (e->k == VKNUM);
++  return (ek && e->t == NO_JUMP && e->f == NO_JUMP);
+ }
+ 
+ 
+@@ -231,12 +236,16 @@ static int addk (FuncState *fs, TValue *
+   TValue *idx = luaH_set(L, fs->h, k);
+   Proto *f = fs->f;
+   int oldsize = f->sizek;
+-  if (ttisnumber(idx)) {
+-    lua_assert(luaO_rawequalObj(&fs->f->k[cast_int(nvalue(idx))], v));
+-    return cast_int(nvalue(idx));
++  if (ttype(idx)==LUA_TNUMBER) {
++    luai_normalize(idx);
++    lua_assert( ttype(idx)==LUA_TINT );     /* had no fraction */
++  }
++  if (ttisint(idx)) {
++    lua_assert(luaO_rawequalObj(&fs->f->k[ivalue(idx)], v));
++    return cast_int(ivalue(idx));
+   }
+   else {  /* constant not found; create a new entry */
+-    setnvalue(idx, cast_num(fs->nk));
++    setivalue(idx, fs->nk);
+     luaM_growvector(L, f->k, fs->nk, f->sizek, TValue,
+                     MAXARG_Bx, "constant table overflow");
+     while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]);
+@@ -261,6 +270,21 @@ int luaK_numberK (FuncState *fs, lua_Num
+ }
+ 
+ 
++int luaK_integerK (FuncState *fs, lua_Integer r) {
++  TValue o;
++  setivalue(&o, r);
++  return addk(fs, &o, &o);
++}
++
++
++#ifdef LNUM_COMPLEX
++static int luaK_imagK (FuncState *fs, lua_Number r) {
++  TValue o;
++  setnvalue_complex(&o, r*I);
++  return addk(fs, &o, &o);
++}
++#endif
++
+ static int boolK (FuncState *fs, int b) {
+   TValue o;
+   setbvalue(&o, b);
+@@ -359,6 +383,16 @@ static void discharge2reg (FuncState *fs
+       luaK_codeABx(fs, OP_LOADK, reg, luaK_numberK(fs, e->u.nval));
+       break;
+     }
++    case VKINT: {
++      luaK_codeABx(fs, OP_LOADK, reg, luaK_integerK(fs, e->u.ival));
++      break;
++    }
++#ifdef LNUM_COMPLEX
++    case VKNUM2: {
++      luaK_codeABx(fs, OP_LOADK, reg, luaK_imagK(fs, e->u.nval));
++      break;
++    }
++#endif
+     case VRELOCABLE: {
+       Instruction *pc = &getcode(fs, e);
+       SETARG_A(*pc, reg);
+@@ -444,6 +478,10 @@ void luaK_exp2val (FuncState *fs, expdes
+ int luaK_exp2RK (FuncState *fs, expdesc *e) {
+   luaK_exp2val(fs, e);
+   switch (e->k) {
++#ifdef LNUM_COMPLEX
++    case VKNUM2:
++#endif
++    case VKINT:
+     case VKNUM:
+     case VTRUE:
+     case VFALSE:
+@@ -451,6 +489,10 @@ int luaK_exp2RK (FuncState *fs, expdesc
+       if (fs->nk <= MAXINDEXRK) {  /* constant fit in RK operand? */
+         e->u.s.info = (e->k == VNIL)  ? nilK(fs) :
+                       (e->k == VKNUM) ? luaK_numberK(fs, e->u.nval) :
++                      (e->k == VKINT) ? luaK_integerK(fs, e->u.ival) :
++#ifdef LNUM_COMPLEX
++                      (e->k == VKNUM2) ? luaK_imagK(fs, e->u.nval) :
++#endif
+                                         boolK(fs, (e->k == VTRUE));
+         e->k = VK;
+         return RKASK(e->u.s.info);
+@@ -540,7 +582,10 @@ void luaK_goiftrue (FuncState *fs, expde
+   int pc;  /* pc of last jump */
+   luaK_dischargevars(fs, e);
+   switch (e->k) {
+-    case VK: case VKNUM: case VTRUE: {
++#ifdef LNUM_COMPLEX
++    case VKNUM2:
++#endif
++    case VKINT: case VK: case VKNUM: case VTRUE: {
+       pc = NO_JUMP;  /* always true; do nothing */
+       break;
+     }
+@@ -590,7 +635,10 @@ static void codenot (FuncState *fs, expd
+       e->k = VTRUE;
+       break;
+     }
+-    case VK: case VKNUM: case VTRUE: {
++#ifdef LNUM_COMPLEX
++    case VKNUM2:
++#endif
++    case VKINT: case VK: case VKNUM: case VTRUE: {
+       e->k = VFALSE;
+       break;
+     }
+@@ -626,25 +674,70 @@ void luaK_indexed (FuncState *fs, expdes
+ 
+ static int constfolding (OpCode op, expdesc *e1, expdesc *e2) {
+   lua_Number v1, v2, r;
++  int vkres= VKNUM;
+   if (!isnumeral(e1) || !isnumeral(e2)) return 0;
+-  v1 = e1->u.nval;
+-  v2 = e2->u.nval;
++
++  /* real and imaginary parts don't mix. */
++#ifdef LNUM_COMPLEX
++  if (e1->k == VKNUM2) {
++    if ((op != OP_UNM) && (e2->k != VKNUM2)) return 0; 
++    vkres= VKNUM2; }
++  else if (e2->k == VKNUM2) { return 0; }
++#endif
++  if ((e1->k == VKINT) && (e2->k == VKINT)) {
++    lua_Integer i1= e1->u.ival, i2= e2->u.ival;
++    lua_Integer rr;
++    int done= 0;
++    /* Integer/integer calculations (may end up producing floating point) */
++    switch (op) {
++      case OP_ADD: done= try_addint( &rr, i1, i2 ); break;
++      case OP_SUB: done= try_subint( &rr, i1, i2 ); break;
++      case OP_MUL: done= try_mulint( &rr, i1, i2 ); break;
++      case OP_DIV: done= try_divint( &rr, i1, i2 ); break;
++      case OP_MOD: done= try_modint( &rr, i1, i2 ); break;
++      case OP_POW: done= try_powint( &rr, i1, i2 ); break;
++      case OP_UNM: done= try_unmint( &rr, i1 ); break;
++      default:     done= 0; break;
++    }
++    if (done) {
++      e1->u.ival = rr;  /* remained within integer range */
++      return 1;
++    }
++  }
++  v1 = (e1->k == VKINT) ? ((lua_Number)e1->u.ival) : e1->u.nval;
++  v2 = (e2->k == VKINT) ? ((lua_Number)e2->u.ival) : e2->u.nval;
++
+   switch (op) {
+     case OP_ADD: r = luai_numadd(v1, v2); break;
+     case OP_SUB: r = luai_numsub(v1, v2); break;
+-    case OP_MUL: r = luai_nummul(v1, v2); break;
++    case OP_MUL: 
++#ifdef LNUM_COMPLEX
++        if (vkres==VKNUM2) return 0;    /* leave to runtime (could do here, but not worth it?) */
++#endif
++        r = luai_nummul(v1, v2); break;
+     case OP_DIV:
+       if (v2 == 0) return 0;  /* do not attempt to divide by 0 */
+-      r = luai_numdiv(v1, v2); break;
++#ifdef LNUM_COMPLEX
++        if (vkres==VKNUM2) return 0;    /* leave to runtime */
++#endif
++        r = luai_numdiv(v1, v2); break;
+     case OP_MOD:
+       if (v2 == 0) return 0;  /* do not attempt to divide by 0 */
++#ifdef LNUM_COMPLEX
++      if (vkres==VKNUM2) return 0;    /* leave to runtime */
++#endif
+       r = luai_nummod(v1, v2); break;
+-    case OP_POW: r = luai_numpow(v1, v2); break;
++    case OP_POW: 
++#ifdef LNUM_COMPLEX
++      if (vkres==VKNUM2) return 0;    /* leave to runtime */
++#endif
++      r = luai_numpow(v1, v2); break;
+     case OP_UNM: r = luai_numunm(v1); break;
+     case OP_LEN: return 0;  /* no constant folding for 'len' */
+     default: lua_assert(0); r = 0; break;
+   }
+   if (luai_numisnan(r)) return 0;  /* do not attempt to produce NaN */
++  e1->k = cast(expkind,vkres);
+   e1->u.nval = r;
+   return 1;
+ }
+@@ -688,7 +781,8 @@ static void codecomp (FuncState *fs, OpC
+ 
+ void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) {
+   expdesc e2;
+-  e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0;
++  e2.t = e2.f = NO_JUMP; e2.k = VKINT; e2.u.ival = 0;
++
+   switch (op) {
+     case OPR_MINUS: {
+       if (!isnumeral(e))
+--- a/src/lcode.h
++++ b/src/lcode.h
+@@ -71,6 +71,6 @@ LUAI_FUNC void luaK_prefix (FuncState *f
+ LUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v);
+ LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, expdesc *v2);
+ LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore);
+-
++LUAI_FUNC int luaK_integerK (FuncState *fs, lua_Integer r);
+ 
+ #endif
+--- a/src/ldebug.c
++++ b/src/ldebug.c
+@@ -183,7 +183,7 @@ static void collectvalidlines (lua_State
+     int *lineinfo = f->l.p->lineinfo;
+     int i;
+     for (i=0; i<f->l.p->sizelineinfo; i++)
+-      setbvalue(luaH_setnum(L, t, lineinfo[i]), 1);
++      setbvalue(luaH_setint(L, t, lineinfo[i]), 1);
+     sethvalue(L, L->top, t); 
+   }
+   incr_top(L);
+@@ -566,7 +566,7 @@ static int isinstack (CallInfo *ci, cons
+ 
+ void luaG_typeerror (lua_State *L, const TValue *o, const char *op) {
+   const char *name = NULL;
+-  const char *t = luaT_typenames[ttype(o)];
++  const char *t = luaT_typenames[ttype_ext(o)];
+   const char *kind = (isinstack(L->ci, o)) ?
+                          getobjname(L, L->ci, cast_int(o - L->base), &name) :
+                          NULL;
+@@ -594,8 +594,8 @@ void luaG_aritherror (lua_State *L, cons
+ 
+ 
+ int luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) {
+-  const char *t1 = luaT_typenames[ttype(p1)];
+-  const char *t2 = luaT_typenames[ttype(p2)];
++  const char *t1 = luaT_typenames[ttype_ext(p1)];
++  const char *t2 = luaT_typenames[ttype_ext(p2)];
+   if (t1[2] == t2[2])
+     luaG_runerror(L, "attempt to compare two %s values", t1);
+   else
+--- a/src/ldo.c
++++ b/src/ldo.c
+@@ -220,9 +220,9 @@ static StkId adjust_varargs (lua_State *
+     luaD_checkstack(L, p->maxstacksize);
+     htab = luaH_new(L, nvar, 1);  /* create `arg' table */
+     for (i=0; i<nvar; i++)  /* put extra arguments into `arg' table */
+-      setobj2n(L, luaH_setnum(L, htab, i+1), L->top - nvar + i);
++      setobj2n(L, luaH_setint(L, htab, i+1), L->top - nvar + i);
+     /* store counter in field `n' */
+-    setnvalue(luaH_setstr(L, htab, luaS_newliteral(L, "n")), cast_num(nvar));
++    setivalue(luaH_setstr(L, htab, luaS_newliteral(L, "n")), nvar);
+   }
+ #endif
+   /* move fixed parameters to final position */
+--- a/src/ldump.c
++++ b/src/ldump.c
+@@ -52,6 +52,11 @@ static void DumpNumber(lua_Number x, Dum
+  DumpVar(x,D);
+ }
+ 
++static void DumpInteger(lua_Integer x, DumpState* D)
++{
++ DumpVar(x,D);
++}
++
+ static void DumpVector(const void* b, int n, size_t size, DumpState* D)
+ {
+  DumpInt(n,D);
+@@ -93,8 +98,11 @@ static void DumpConstants(const Proto* f
+ 	DumpChar(bvalue(o),D);
+ 	break;
+    case LUA_TNUMBER:
+-	DumpNumber(nvalue(o),D);
++	DumpNumber(nvalue_fast(o),D);
+ 	break;
++   case LUA_TINT:
++	DumpInteger(ivalue(o),D);
++    break;
+    case LUA_TSTRING:
+ 	DumpString(rawtsvalue(o),D);
+ 	break;
+--- a/src/liolib.c
++++ b/src/liolib.c
+@@ -9,6 +9,7 @@
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
++#include <ctype.h>
+ 
+ #define liolib_c
+ #define LUA_LIB
+@@ -18,7 +19,8 @@
+ #include "lauxlib.h"
+ #include "lualib.h"
+ 
+-
++#include "lnum.h"
++#include "llex.h"
+ 
+ #define IO_INPUT	1
+ #define IO_OUTPUT	2
+@@ -269,6 +271,13 @@ static int io_lines (lua_State *L) {
+ ** =======================================================
+ */
+ 
++/*
++* Many problems if we intend the same 'n' format specifier (see 'file:read()')
++* to work for both FP and integer numbers, without losing their accuracy. So
++* we don't. 'n' reads numbers as floating points, 'i' as integers. Old code
++* remains valid, but won't provide full integer accuracy (this only matters
++* with float FP and/or 64-bit integers).
++*/
+ 
+ static int read_number (lua_State *L, FILE *f) {
+   lua_Number d;
+@@ -282,6 +291,43 @@ static int read_number (lua_State *L, FI
+   }
+ }
+ 
++static int read_integer (lua_State *L, FILE *f) {
++  lua_Integer i;
++  if (fscanf(f, LUA_INTEGER_SCAN, &i) == 1) {
++    lua_pushinteger(L, i);
++    return 1;
++  }
++  else return 0;  /* read fails */
++}
++
++#ifdef LNUM_COMPLEX
++static int read_complex (lua_State *L, FILE *f) {
++  /* NNN / NNNi / NNN+MMMi / NNN-MMMi */
++  lua_Number a,b;
++  if (fscanf(f, LUA_NUMBER_SCAN, &a) == 1) {
++    int c=fgetc(f);
++    switch(c) {
++        case 'i':
++            lua_pushcomplex(L, a*I);
++            return 1;
++        case '+':
++        case '-':
++            /* "i" is consumed if at the end; just 'NNN+MMM' will most likely
++             * behave as if "i" was there? (TBD: test)
++             */
++            if (fscanf(f, LUA_NUMBER_SCAN "i", &b) == 1) {
++                lua_pushcomplex(L, a+ (c=='+' ? b:-b)*I);
++                return 1;
++            }
++    }
++    ungetc( c,f );
++    lua_pushnumber(L,a);  /*real part only*/
++    return 1;
++  }
++  return 0;  /* read fails */
++}
++#endif
++
+ 
+ static int test_eof (lua_State *L, FILE *f) {
+   int c = getc(f);
+@@ -355,6 +401,14 @@ static int g_read (lua_State *L, FILE *f
+           case 'n':  /* number */
+             success = read_number(L, f);
+             break;
++          case 'i':  /* integer (full accuracy) */
++            success = read_integer(L, f);
++            break;
++#ifdef LNUM_COMPLEX
++          case 'c':  /* complex */
++            success = read_complex(L, f);
++            break;
++#endif
+           case 'l':  /* line */
+             success = read_line(L, f);
+             break;
+@@ -415,9 +469,10 @@ static int g_write (lua_State *L, FILE *
+   int status = 1;
+   for (; nargs--; arg++) {
+     if (lua_type(L, arg) == LUA_TNUMBER) {
+-      /* optimization: could be done exactly as for strings */
+-      status = status &&
+-          fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0;
++      if (lua_isinteger(L,arg))
++          status = status && fprintf(f, LUA_INTEGER_FMT, lua_tointeger(L, arg)) > 0;
++      else
++          status = status && fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0;
+     }
+     else {
+       size_t l;
+@@ -460,7 +515,7 @@ static int f_setvbuf (lua_State *L) {
+   static const char *const modenames[] = {"no", "full", "line", NULL};
+   FILE *f = tofile(L);
+   int op = luaL_checkoption(L, 2, NULL, modenames);
+-  lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE);
++  size_t sz = luaL_optint32(L, 3, LUAL_BUFFERSIZE);
+   int res = setvbuf(f, NULL, mode[op], sz);
+   return pushresult(L, res == 0, NULL);
+ }
+--- a/src/llex.c
++++ b/src/llex.c
+@@ -22,6 +22,7 @@
+ #include "lstring.h"
+ #include "ltable.h"
+ #include "lzio.h"
++#include "lnum.h"
+ 
+ 
+ 
+@@ -34,13 +35,17 @@
+ 
+ 
+ /* ORDER RESERVED */
+-const char *const luaX_tokens [] = {
++static const char *const luaX_tokens [] = {
+     "and", "break", "do", "else", "elseif",
+     "end", "false", "for", "function", "if",
+     "in", "local", "nil", "not", "or", "repeat",
+     "return", "then", "true", "until", "while",
+     "..", "...", "==", ">=", "<=", "~=",
+     "<number>", "<name>", "<string>", "<eof>",
++    "<integer>",
++#ifdef LNUM_COMPLEX
++    "<number2>",
++#endif
+     NULL
+ };
+ 
+@@ -90,7 +95,11 @@ static const char *txtToken (LexState *l
+   switch (token) {
+     case TK_NAME:
+     case TK_STRING:
++    case TK_INT:
+     case TK_NUMBER:
++#ifdef LNUM_COMPLEX
++    case TK_NUMBER2:
++#endif
+       save(ls, '\0');
+       return luaZ_buffer(ls->buff);
+     default:
+@@ -175,23 +184,27 @@ static void buffreplace (LexState *ls, c
+     if (p[n] == from) p[n] = to;
+ }
+ 
+-
+-static void trydecpoint (LexState *ls, SemInfo *seminfo) {
++/* TK_NUMBER (/ TK_NUMBER2) */
++static int trydecpoint (LexState *ls, SemInfo *seminfo) {
+   /* format error: try to update decimal point separator */
+   struct lconv *cv = localeconv();
+   char old = ls->decpoint;
++  int ret;
+   ls->decpoint = (cv ? cv->decimal_point[0] : '.');
+   buffreplace(ls, old, ls->decpoint);  /* try updated decimal separator */
+-  if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) {
++  ret= luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r, NULL);
++  if (!ret) {
+     /* format error with correct decimal point: no more options */
+     buffreplace(ls, ls->decpoint, '.');  /* undo change (for error message) */
+     luaX_lexerror(ls, "malformed number", TK_NUMBER);
+   }
++  return ret;
+ }
+ 
+ 
+-/* LUA_NUMBER */
+-static void read_numeral (LexState *ls, SemInfo *seminfo) {
++/* TK_NUMBER / TK_INT (/TK_NUMBER2) */
++static int read_numeral (LexState *ls, SemInfo *seminfo) {
++  int ret;
+   lua_assert(isdigit(ls->current));
+   do {
+     save_and_next(ls);
+@@ -202,8 +215,9 @@ static void read_numeral (LexState *ls,
+     save_and_next(ls);
+   save(ls, '\0');
+   buffreplace(ls, '.', ls->decpoint);  /* follow locale for decimal point */
+-  if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r))  /* format error? */
+-    trydecpoint(ls, seminfo); /* try to update decimal point separator */
++  ret= luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r, &seminfo->i );
++  if (!ret) return trydecpoint(ls, seminfo); /* try to update decimal point separator */
++  return ret;
+ }
+ 
+ 
+@@ -331,6 +345,7 @@ static void read_string (LexState *ls, i
+ }
+ 
+ 
++/* char / TK_* */
+ static int llex (LexState *ls, SemInfo *seminfo) {
+   luaZ_resetbuffer(ls->buff);
+   for (;;) {
+@@ -402,8 +417,7 @@ static int llex (LexState *ls, SemInfo *
+         }
+         else if (!isdigit(ls->current)) return '.';
+         else {
+-          read_numeral(ls, seminfo);
+-          return TK_NUMBER;
++          return read_numeral(ls, seminfo);
+         }
+       }
+       case EOZ: {
+@@ -416,8 +430,7 @@ static int llex (LexState *ls, SemInfo *
+           continue;
+         }
+         else if (isdigit(ls->current)) {
+-          read_numeral(ls, seminfo);
+-          return TK_NUMBER;
++          return read_numeral(ls, seminfo);
+         }
+         else if (isalpha(ls->current) || ls->current == '_') {
+           /* identifier or reserved word */
+--- a/src/llex.h
++++ b/src/llex.h
+@@ -29,19 +29,22 @@ enum RESERVED {
+   TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE,
+   /* other terminal symbols */
+   TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_NUMBER,
+-  TK_NAME, TK_STRING, TK_EOS
++  TK_NAME, TK_STRING, TK_EOS, TK_INT
++#ifdef LNUM_COMPLEX
++  , TK_NUMBER2   /* imaginary constants: Ni */ 
++#endif
+ };
+ 
+ /* number of reserved words */
+ #define NUM_RESERVED	(cast(int, TK_WHILE-FIRST_RESERVED+1))
+ 
+ 
+-/* array with token `names' */
+-LUAI_DATA const char *const luaX_tokens [];
+-
+-
++/* SemInfo is a local data structure of 'llex.c', used for carrying a string
++ * or a number. A separate token (TK_*) will tell, how to interpret the data.
++ */      
+ typedef union {
+   lua_Number r;
++  lua_Integer i;
+   TString *ts;
+ } SemInfo;  /* semantics information */
+ 
+--- a/src/llimits.h
++++ b/src/llimits.h
+@@ -49,6 +49,7 @@ typedef LUAI_USER_ALIGNMENT_T L_Umaxalig
+ 
+ /* result of a `usual argument conversion' over lua_Number */
+ typedef LUAI_UACNUMBER l_uacNumber;
++typedef LUAI_UACINTEGER l_uacInteger;
+ 
+ 
+ /* internal assertions for in-house debugging */
+@@ -80,7 +81,6 @@ typedef LUAI_UACNUMBER l_uacNumber;
+ #define cast_int(i)	cast(int, (i))
+ 
+ 
+-
+ /*
+ ** type for virtual-machine instructions
+ ** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h)
+--- a/src/lmathlib.c
++++ b/src/lmathlib.c
+@@ -4,7 +4,6 @@
+ ** See Copyright Notice in lua.h
+ */
+ 
+-
+ #include <stdlib.h>
+ #include <math.h>
+ 
+@@ -16,113 +15,210 @@
+ #include "lauxlib.h"
+ #include "lualib.h"
+ 
++/* 'luai_vectpow()' as a replacement for 'cpow()'. Defined in the header; we
++ * don't intrude the code libs internal functions.
++ */
++#ifdef LNUM_COMPLEX
++# include "lnum.h"    
++#endif
+ 
+ #undef PI
+-#define PI (3.14159265358979323846)
+-#define RADIANS_PER_DEGREE (PI/180.0)
+-
+-
++#ifdef LNUM_FLOAT
++# define PI (3.14159265358979323846F)
++#elif defined(M_PI)
++# define PI M_PI
++#else
++# define PI (3.14159265358979323846264338327950288)
++#endif
++#define RADIANS_PER_DEGREE (PI/180)
++
++#undef HUGE
++#ifdef LNUM_FLOAT
++# define HUGE HUGE_VALF
++#elif defined(LNUM_LDOUBLE)
++# define HUGE HUGE_VALL
++#else
++# define HUGE HUGE_VAL
++#endif
+ 
+ static int math_abs (lua_State *L) {
+-  lua_pushnumber(L, fabs(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++  lua_pushnumber(L, _LF(cabs) (luaL_checkcomplex(L,1)));
++#else
++  lua_pushnumber(L, _LF(fabs) (luaL_checknumber(L, 1)));
++#endif
+   return 1;
+ }
+ 
+ static int math_sin (lua_State *L) {
+-  lua_pushnumber(L, sin(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++  lua_pushcomplex(L, _LF(csin) (luaL_checkcomplex(L,1)));
++#else
++  lua_pushnumber(L, _LF(sin) (luaL_checknumber(L, 1)));
++#endif
+   return 1;
+ }
+ 
+ static int math_sinh (lua_State *L) {
+-  lua_pushnumber(L, sinh(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++  lua_pushcomplex(L, _LF(csinh) (luaL_checkcomplex(L,1)));
++#else
++  lua_pushnumber(L, _LF(sinh) (luaL_checknumber(L, 1)));
++#endif
+   return 1;
+ }
+ 
+ static int math_cos (lua_State *L) {
+-  lua_pushnumber(L, cos(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++  lua_pushcomplex(L, _LF(ccos) (luaL_checkcomplex(L,1)));
++#else
++  lua_pushnumber(L, _LF(cos) (luaL_checknumber(L, 1)));
++#endif
+   return 1;
+ }
+ 
+ static int math_cosh (lua_State *L) {
+-  lua_pushnumber(L, cosh(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++  lua_pushcomplex(L, _LF(ccosh) (luaL_checkcomplex(L,1)));
++#else
++  lua_pushnumber(L, _LF(cosh) (luaL_checknumber(L, 1)));
++#endif
+   return 1;
+ }
+ 
+ static int math_tan (lua_State *L) {
+-  lua_pushnumber(L, tan(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++  lua_pushcomplex(L, _LF(ctan) (luaL_checkcomplex(L,1)));
++#else
++  lua_pushnumber(L, _LF(tan) (luaL_checknumber(L, 1)));
++#endif
+   return 1;
+ }
+ 
+ static int math_tanh (lua_State *L) {
+-  lua_pushnumber(L, tanh(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++  lua_pushcomplex(L, _LF(ctanh) (luaL_checkcomplex(L,1)));
++#else
++  lua_pushnumber(L, _LF(tanh) (luaL_checknumber(L, 1)));
++#endif
+   return 1;
+ }
+ 
+ static int math_asin (lua_State *L) {
+-  lua_pushnumber(L, asin(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++  lua_pushcomplex(L, _LF(casin) (luaL_checkcomplex(L,1)));
++#else
++  lua_pushnumber(L, _LF(asin) (luaL_checknumber(L, 1)));
++#endif
+   return 1;
+ }
+ 
+ static int math_acos (lua_State *L) {
+-  lua_pushnumber(L, acos(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++  lua_pushcomplex(L, _LF(cacos) (luaL_checkcomplex(L,1)));
++#else
++  lua_pushnumber(L, _LF(acos) (luaL_checknumber(L, 1)));
++#endif
+   return 1;
+ }
+ 
+ static int math_atan (lua_State *L) {
+-  lua_pushnumber(L, atan(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++  lua_pushcomplex(L, _LF(catan) (luaL_checkcomplex(L,1)));
++#else
++  lua_pushnumber(L, _LF(atan) (luaL_checknumber(L, 1)));
++#endif
+   return 1;
+ }
+ 
+ static int math_atan2 (lua_State *L) {
+-  lua_pushnumber(L, atan2(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
++  /* scalars only */
++  lua_pushnumber(L, _LF(atan2) (luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
+   return 1;
+ }
+ 
+ static int math_ceil (lua_State *L) {
+-  lua_pushnumber(L, ceil(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++  lua_Complex v= luaL_checkcomplex(L, 1);
++  lua_pushcomplex(L, _LF(ceil) (_LF(creal)(v)) + _LF(ceil) (_LF(cimag)(v))*I);
++#else
++  lua_pushnumber(L, _LF(ceil) (luaL_checknumber(L, 1)));
++#endif
+   return 1;
+ }
+ 
+ static int math_floor (lua_State *L) {
+-  lua_pushnumber(L, floor(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++  lua_Complex v= luaL_checkcomplex(L, 1);
++  lua_pushcomplex(L, _LF(floor) (_LF(creal)(v)) + _LF(floor) (_LF(cimag)(v))*I);
++#else
++  lua_pushnumber(L, _LF(floor) (luaL_checknumber(L, 1)));
++#endif
+   return 1;
+ }
+ 
+-static int math_fmod (lua_State *L) {
+-  lua_pushnumber(L, fmod(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
++static int math_fmod (lua_State *L) {  
++  /* scalars only */
++  lua_pushnumber(L, _LF(fmod) (luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
+   return 1;
+ }
+ 
+ static int math_modf (lua_State *L) {
+-  double ip;
+-  double fp = modf(luaL_checknumber(L, 1), &ip);
++  /* scalars only */
++  lua_Number ip;
++  lua_Number fp = _LF(modf) (luaL_checknumber(L, 1), &ip);
+   lua_pushnumber(L, ip);
+   lua_pushnumber(L, fp);
+   return 2;
+ }
+ 
+ static int math_sqrt (lua_State *L) {
+-  lua_pushnumber(L, sqrt(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++  lua_pushcomplex(L, _LF(csqrt) (luaL_checkcomplex(L,1)));
++#else
++  lua_pushnumber(L, _LF(sqrt) (luaL_checknumber(L, 1)));
++#endif
+   return 1;
+ }
+ 
+ static int math_pow (lua_State *L) {
+-  lua_pushnumber(L, pow(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
++#ifdef LNUM_COMPLEX
++  /* C99 'cpow' gives somewhat inaccurate results (i.e. (-1)^2 = -1+1.2246467991474e-16i). 
++  * 'luai_vectpow' smoothens such, reusing it is the reason we need to #include "lnum.h".
++  */
++  lua_pushcomplex(L, luai_vectpow(luaL_checkcomplex(L,1), luaL_checkcomplex(L,2)));
++#else
++  lua_pushnumber(L, _LF(pow) (luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
++#endif
+   return 1;
+ }
+ 
+ static int math_log (lua_State *L) {
+-  lua_pushnumber(L, log(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++  lua_pushcomplex(L, _LF(clog) (luaL_checkcomplex(L,1)));
++#else
++  lua_pushnumber(L, _LF(log) (luaL_checknumber(L, 1)));
++#endif
+   return 1;
+ }
+ 
+ static int math_log10 (lua_State *L) {
+-  lua_pushnumber(L, log10(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++  /* Not in standard <complex.h> , but easy to calculate: log_a(x) = log_b(x) / log_b(a) 
++  */
++  lua_pushcomplex(L, _LF(clog) (luaL_checkcomplex(L,1)) / _LF(log) (10));
++#else
++  lua_pushnumber(L, _LF(log10) (luaL_checknumber(L, 1)));
++#endif
+   return 1;
+ }
+ 
+ static int math_exp (lua_State *L) {
+-  lua_pushnumber(L, exp(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++  lua_pushcomplex(L, _LF(cexp) (luaL_checkcomplex(L,1)));
++#else
++  lua_pushnumber(L, _LF(exp) (luaL_checknumber(L, 1)));
++#endif
+   return 1;
+ }
+ 
+@@ -138,19 +234,20 @@ static int math_rad (lua_State *L) {
+ 
+ static int math_frexp (lua_State *L) {
+   int e;
+-  lua_pushnumber(L, frexp(luaL_checknumber(L, 1), &e));
++  lua_pushnumber(L, _LF(frexp) (luaL_checknumber(L, 1), &e));
+   lua_pushinteger(L, e);
+   return 2;
+ }
+ 
+ static int math_ldexp (lua_State *L) {
+-  lua_pushnumber(L, ldexp(luaL_checknumber(L, 1), luaL_checkint(L, 2)));
++  lua_pushnumber(L, _LF(ldexp) (luaL_checknumber(L, 1), luaL_checkint(L, 2)));
+   return 1;
+ }
+ 
+ 
+ 
+ static int math_min (lua_State *L) {
++  /* scalars only */
+   int n = lua_gettop(L);  /* number of arguments */
+   lua_Number dmin = luaL_checknumber(L, 1);
+   int i;
+@@ -165,6 +262,7 @@ static int math_min (lua_State *L) {
+ 
+ 
+ static int math_max (lua_State *L) {
++  /* scalars only */
+   int n = lua_gettop(L);  /* number of arguments */
+   lua_Number dmax = luaL_checknumber(L, 1);
+   int i;
+@@ -182,25 +280,20 @@ static int math_random (lua_State *L) {
+   /* the `%' avoids the (rare) case of r==1, and is needed also because on
+      some systems (SunOS!) `rand()' may return a value larger than RAND_MAX */
+   lua_Number r = (lua_Number)(rand()%RAND_MAX) / (lua_Number)RAND_MAX;
+-  switch (lua_gettop(L)) {  /* check number of arguments */
+-    case 0: {  /* no arguments */
+-      lua_pushnumber(L, r);  /* Number between 0 and 1 */
+-      break;
+-    }
+-    case 1: {  /* only upper limit */
+-      int u = luaL_checkint(L, 1);
+-      luaL_argcheck(L, 1<=u, 1, "interval is empty");
+-      lua_pushnumber(L, floor(r*u)+1);  /* int between 1 and `u' */
+-      break;
+-    }
+-    case 2: {  /* lower and upper limits */
+-      int l = luaL_checkint(L, 1);
+-      int u = luaL_checkint(L, 2);
+-      luaL_argcheck(L, l<=u, 2, "interval is empty");
+-      lua_pushnumber(L, floor(r*(u-l+1))+l);  /* int between `l' and `u' */
+-      break;
+-    }
+-    default: return luaL_error(L, "wrong number of arguments");
++  int n= lua_gettop(L);  /* number of arguments */
++  if (n==0) {	/* no arguments: range [0,1) */
++    lua_pushnumber(L, r);
++  } else if (n<=2) {	/* int range [1,u] or [l,u] */
++    int l= n==1 ? 1 : luaL_checkint(L, 1);
++    int u = luaL_checkint(L, n);
++    int tmp;
++    lua_Number d;
++    luaL_argcheck(L, l<=u, n, "interval is empty");
++    d= _LF(floor)(r*(u-l+1));
++    lua_number2int(tmp,d);
++    lua_pushinteger(L, l+tmp);
++  } else {
++    return luaL_error(L, "wrong number of arguments");
+   }
+   return 1;
+ }
+@@ -211,6 +304,66 @@ static int math_randomseed (lua_State *L
+   return 0;
+ }
+ 
++/* 
++* Lua 5.1 does not have acosh, asinh, atanh for scalars (not ANSI C)
++*/
++#if __STDC_VERSION__ >= 199901L
++static int math_acosh (lua_State *L) {
++# ifdef LNUM_COMPLEX
++  lua_pushcomplex(L, _LF(cacosh) (luaL_checkcomplex(L,1)));
++# else
++  lua_pushnumber(L, _LF(acosh) (luaL_checknumber(L,1)));
++# endif
++  return 1;
++}
++static int math_asinh (lua_State *L) {
++# ifdef LNUM_COMPLEX
++  lua_pushcomplex(L, _LF(casinh) (luaL_checkcomplex(L,1)));
++# else
++  lua_pushnumber(L, _LF(asinh) (luaL_checknumber(L,1)));
++# endif
++  return 1;
++}
++static int math_atanh (lua_State *L) {
++# ifdef LNUM_COMPLEX
++  lua_pushcomplex(L, _LF(catanh) (luaL_checkcomplex(L,1)));
++# else
++  lua_pushnumber(L, _LF(atanh) (luaL_checknumber(L,1)));
++# endif
++  return 1;
++}
++#endif
++
++/* 
++ * C99 complex functions, not covered above.
++*/
++#ifdef LNUM_COMPLEX
++static int math_arg (lua_State *L) {
++  lua_pushnumber(L, _LF(carg) (luaL_checkcomplex(L,1)));
++  return 1;
++}
++
++static int math_imag (lua_State *L) {
++  lua_pushnumber(L, _LF(cimag) (luaL_checkcomplex(L,1)));
++  return 1;
++}
++
++static int math_real (lua_State *L) {
++  lua_pushnumber(L, _LF(creal) (luaL_checkcomplex(L,1)));
++  return 1;
++}
++
++static int math_conj (lua_State *L) {
++  lua_pushcomplex(L, _LF(conj) (luaL_checkcomplex(L,1)));
++  return 1;
++}
++
++static int math_proj (lua_State *L) {
++  lua_pushcomplex(L, _LF(cproj) (luaL_checkcomplex(L,1)));
++  return 1;
++}
++#endif
++
+ 
+ static const luaL_Reg mathlib[] = {
+   {"abs",   math_abs},
+@@ -241,6 +394,18 @@ static const luaL_Reg mathlib[] = {
+   {"sqrt",  math_sqrt},
+   {"tanh",   math_tanh},
+   {"tan",   math_tan},
++#if __STDC_VERSION__ >= 199901L
++  {"acosh",  math_acosh},
++  {"asinh",  math_asinh},
++  {"atanh",  math_atanh},
++#endif
++#ifdef LNUM_COMPLEX
++  {"arg",   math_arg},
++  {"imag",  math_imag},
++  {"real",  math_real},
++  {"conj",  math_conj},
++  {"proj",  math_proj},
++#endif
+   {NULL, NULL}
+ };
+ 
+@@ -252,8 +417,10 @@ LUALIB_API int luaopen_math (lua_State *
+   luaL_register(L, LUA_MATHLIBNAME, mathlib);
+   lua_pushnumber(L, PI);
+   lua_setfield(L, -2, "pi");
+-  lua_pushnumber(L, HUGE_VAL);
++  lua_pushnumber(L, HUGE);
+   lua_setfield(L, -2, "huge");
++  lua_pushinteger(L, LUA_INTEGER_MAX );
++  lua_setfield(L, -2, "hugeint");
+ #if defined(LUA_COMPAT_MOD)
+   lua_getfield(L, -1, "fmod");
+   lua_setfield(L, -2, "mod");
+--- /dev/null
++++ b/src/lnum.c
+@@ -0,0 +1,312 @@
++/*
++** $Id: lnum.c,v ... $
++** Internal number model
++** See Copyright Notice in lua.h
++*/
++
++#include <stdlib.h>
++#include <math.h>
++#include <ctype.h>
++#include <string.h>
++#include <stdio.h>
++#include <errno.h>
++
++#define lnum_c
++#define LUA_CORE
++
++#include "lua.h"
++#include "llex.h"
++#include "lnum.h"
++
++/*
++** lua_real2str converts a (non-complex) number to a string.
++** lua_str2real converts a string to a (non-complex) number.
++*/
++#define lua_real2str(s,n)  sprintf((s), LUA_NUMBER_FMT, (n))
++
++/*
++* Note: Only 'strtod()' is part of ANSI C; others are C99 and
++* may need '--std=c99' compiler setting (at least on Ubuntu 7.10).
++* 
++* Visual C++ 2008 Express does not have 'strtof()', nor 'strtold()'.
++* References to '_strtold()' exist but don't compile. It seems best
++* to leave Windows users with DOUBLE only (or compile with MinGW).
++*
++* In practise, using '(long double)strtod' is a risky thing, since
++* it will cause accuracy loss in reading in numbers, and such losses
++* will pile up in later processing. Get a real 'strtold()' or don't
++* use that mode at all.
++*/
++#ifdef LNUM_DOUBLE
++# define lua_str2real	strtod
++#elif defined(LNUM_FLOAT)
++# define lua_str2real	strtof
++#elif defined(LNUM_LDOUBLE)
++# define lua_str2real	strtold
++#endif
++
++#define lua_integer2str(s,v) sprintf((s), LUA_INTEGER_FMT, (v))
++
++/* 's' is expected to be LUAI_MAXNUMBER2STR long (enough for any number)
++*/
++void luaO_num2buf( char *s, const TValue *o )
++{
++  lua_Number n;
++  lua_assert( ttisnumber(o) );
++
++  /* Reason to handle integers differently is not only speed, but accuracy as
++   * well. We want to make any integer tostring() without roundings, at all.
++   */
++  if (ttisint(o)) {
++    lua_integer2str( s, ivalue(o) );
++    return;
++  }
++  n= nvalue_fast(o);
++  lua_real2str(s, n);
++
++#ifdef LNUM_COMPLEX
++  lua_Number n2= nvalue_img_fast(o);
++  if (n2!=0) {   /* Postfix with +-Ni */
++      int re0= (n == 0);
++      char *s2= re0 ? s : strchr(s,'\0'); 
++      if ((!re0) && (n2>0)) *s2++= '+';
++      lua_real2str( s2, n2 );
++      strcat(s2,"i");
++  }
++#endif
++}
++
++/*
++* If a LUA_TNUMBER has integer value, give it.
++*/
++int /*bool*/ tt_integer_valued( const TValue *o, lua_Integer *ref ) {
++  lua_Number d;
++  lua_Integer i;
++
++  lua_assert( ttype(o)==LUA_TNUMBER );
++  lua_assert( ref );
++#ifdef LNUM_COMPLEX
++  if (nvalue_img_fast(o)!=0) return 0;
++#endif
++  d= nvalue_fast(o);
++  lua_number2integer(i, d);
++  if (cast_num(i) == d) {
++    *ref= i; return 1;
++  }
++  return 0;
++}
++
++/* 
++ * Lua 5.1.3 (using 'strtod()') allows 0x+hex but not 0+octal. This is good,
++ * and we should NOT use 'autobase' 0 with 'strtoul[l]()' for this reason.
++ *
++ * Lua 5.1.3 allows '0x...' numbers to overflow and lose precision; this is not
++ * good. On Visual C++ 2008, 'strtod()' does not even take them in. Better to
++ * require hex values to fit 'lua_Integer' or give an error that they don't?
++ *
++ * Full hex range (0 .. 0xff..ff) is stored as integers, not to lose any bits.
++ * Numerical value of 0xff..ff will be -1, if used in calculations.
++ * 
++ * Returns: TK_INT for a valid integer, '*endptr_ref' updated
++ *          TK_NUMBER for seemingly numeric, to be parsed as floating point
++ *          0 for bad characters, not a number (or '0x' out of range)
++ */
++static int luaO_str2i (const char *s, lua_Integer *res, char **endptr_ref) {
++  char *endptr;
++  /* 'v' gets ULONG_MAX on possible overflow (which is > LUA_INTEGER_MAX);
++   * we don't have to check 'errno' here.
++   */
++  unsigned LUA_INTEGER v= lua_str2ul(s, &endptr, 10);
++  if (endptr == s) return 0;  /* nothing numeric */
++  if (v==0 && *endptr=='x') {
++    errno= 0;   /* needs to be set, 'strtoul[l]' does not clear it */
++    v= lua_str2ul(endptr+1, &endptr, 16);  /* retry as hex, unsigned range */
++    if (errno==ERANGE) {   /* clamped to 0xff..ff */
++#if (defined(LNUM_INT32) && !defined(LNUM_FLOAT)) || defined(LNUM_LDOUBLE)
++      return TK_NUMBER; /* Allow to be read as floating point (has more integer range) */
++#else
++      return 0;  /* Reject the number */
++#endif
++    }
++  } else if ((v > LUA_INTEGER_MAX) || (*endptr && (!isspace(*endptr)))) {
++    return TK_NUMBER;	/* not in signed range, or has '.', 'e' etc. trailing */
++  }
++  *res= (lua_Integer)v;
++  *endptr_ref= endptr;
++  return TK_INT;
++}
++
++/* 0 / TK_NUMBER / TK_INT (/ TK_NUMBER2) */
++int luaO_str2d (const char *s, lua_Number *res_n, lua_Integer *res_i) {
++  char *endptr;
++  int ret= TK_NUMBER;
++  /* Check integers first, if caller is allowing. 
++   * If 'res2'==NULL, they're only looking for floating point. 
++   */
++  if (res_i) {
++    ret= luaO_str2i(s,res_i,&endptr);
++    if (ret==0) return 0;
++  }
++  if (ret==TK_NUMBER) {
++    lua_assert(res_n);
++    /* Note: Visual C++ 2008 Express 'strtod()' does not read in "0x..."
++     *       numbers; it will read '0' and spit 'x' as endptr.
++     *       This means hex constants not fitting in 'lua_Integer' won't 
++     *       be read in at all. What to do?
++     */
++    *res_n = lua_str2real(s, &endptr);
++    if (endptr == s) return 0;  /* conversion failed */
++    /* Visual C++ 2008 'strtod()' does not allow "0x..." input. */
++#if defined(_MSC_VER) && !defined(LNUM_FLOAT) && !defined(LNUM_INT64)
++    if (*res_n==0 && *endptr=='x') {
++      /* Hex constant too big for 'lua_Integer' but that could fit in 'lua_Number'
++       * integer bits 
++       */
++      unsigned __int64 v= _strtoui64( s, &endptr, 16 );
++      /* We just let > 64 bit values be clamped to _UI64_MAX (MSDN does not say 'errno'==ERANGE would be set) */
++      *res_n= cast_num(v);
++      if (*res_n != v) return 0;    /* Would have lost accuracy */
++    }
++#endif
++#ifdef LNUM_COMPLEX
++    if (*endptr == 'i') { endptr++; ret= TK_NUMBER2; }
++#endif
++  }
++  if (*endptr) {
++    while (isspace(cast(unsigned char, *endptr))) endptr++;
++    if (*endptr) return 0;  /* invalid trail */
++  }
++  return ret;
++}
++
++
++/* Functions for finding out, when integer operations remain in range
++ * (and doing them).
++ */
++int try_addint( lua_Integer *r, lua_Integer ib, lua_Integer ic ) {
++  /* Signed int overflow is undefined behavior, so catch it without causing it. */
++  if (ic>0)  { if (ib > LUA_INTEGER_MAX - ic) return 0; /*overflow, use floats*/ }
++  else       { if (ib < LUA_INTEGER_MIN - ic) return 0; }
++  *r = ib + ic;
++  return 1;
++}
++
++int try_subint( lua_Integer *r, lua_Integer ib, lua_Integer ic ) {
++  /* Signed int overflow is undefined behavior, so catch it without causing it. */
++  if (ic>0)  { if (ib < LUA_INTEGER_MIN + ic) return 0; /*overflow, use floats*/ }
++  else       { if (ib > LUA_INTEGER_MAX + ic) return 0; }
++  *r = ib - ic;
++  return 1;
++}
++
++int try_mulint( lua_Integer *r, lua_Integer ib, lua_Integer ic ) {
++  if (ib!=LUA_INTEGER_MIN && ic!=LUA_INTEGER_MIN) {
++    lua_Integer b= luai_abs(ib), c= luai_abs(ic);
++    if ( (ib==0) || (LUA_INTEGER_MAX/b >= c) ) {
++      *r= ib*ic;  /* no overflow */
++      return 1;
++    }
++  } else if (ib==0 || ic==0) {
++    *r= 0; return 1;
++  }
++
++  /* Result can be LUA_INTEGER_MIN; if it is, calculating it using floating 
++   * point will not cause accuracy loss.
++   */
++  if ( luai_nummul( cast_num(ib), cast_num(ic) ) == LUA_INTEGER_MIN ) {
++    *r= LUA_INTEGER_MIN;
++    return 1;
++  }
++  return 0;
++}
++
++int try_divint( lua_Integer *r, lua_Integer ib, lua_Integer ic ) {
++  /* N/0: leave to float side, to give an error
++  */
++  if (ic==0) return 0;
++
++  /* N/LUA_INTEGER_MIN: always non-integer results, or 0 or +1
++  */
++  if (ic==LUA_INTEGER_MIN) {
++    if (ib==LUA_INTEGER_MIN) { *r=1; return 1; }
++    if (ib==0) { *r=0; return 1; }
++
++  /* LUA_INTEGER_MIN (-2^31|63)/N: calculate using float side (either the division 
++   *    causes non-integer results, or there is no accuracy loss in int->fp->int
++   *    conversions (N=2,4,8,..,256 and N=2^30,2^29,..2^23).
++   */
++  } else if (ib==LUA_INTEGER_MIN) {
++    lua_Number d= luai_numdiv( cast_num(LUA_INTEGER_MIN), cast_num(ic) );
++    lua_Integer i; lua_number2integer(i,d);
++    if (cast_num(i)==d) { *r= i; return 1; }
++  
++  } else {
++    /* Note: We _can_ use ANSI C mod here, even on negative values, since
++     *       we only test for == 0 (the sign would be implementation dependent).
++     */
++     if (ib%ic == 0) { *r= ib/ic; return 1; }
++  }
++
++  return 0;
++}
++
++int try_modint( lua_Integer *r, lua_Integer ib, lua_Integer ic ) {
++  if (ic!=0) {
++    /* ANSI C can be trusted when b%c==0, or when values are non-negative. 
++     * b - (floor(b/c) * c)
++     *   -->
++     * + +: b - (b/c) * c (b % c can be used)
++     * - -: b - (b/c) * c (b % c could work, but not defined by ANSI C)
++     * 0 -: b - (b/c) * c (=0, b % c could work, but not defined by ANSI C)
++     * - +: b - (b/c-1) * c (when b!=-c)
++     * + -: b - (b/c-1) * c (when b!=-c)
++     *
++     * o MIN%MIN ends up 0, via overflow in calcs but that does not matter.
++     * o MIN%MAX ends up MAX-1 (and other such numbers), also after overflow,
++     *   but that does not matter, results do.
++     */
++    lua_Integer v= ib % ic;
++    if ( v!=0 && (ib<0 || ic<0) ) {
++      v= ib - ((ib/ic) - ((ib<=0 && ic<0) ? 0:1)) * ic;
++    }      
++    /* Result should always have same sign as 2nd argument. (PIL2) */
++    lua_assert( (v<0) ? (ic<0) : (v>0) ? (ic>0) : 1 );
++    *r= v;
++    return 1;
++  }
++  return 0;  /* let float side return NaN */
++}
++
++int try_powint( lua_Integer *r, lua_Integer ib, lua_Integer ic ) {
++
++    /* In FLOAT/INT32 or FLOAT|DOUBLE/INT64 modes, calculating integer powers 
++     * via FP realm may lose accuracy (i.e. 7^11 = 1977326743, which fits int32
++     * but not 23-bit float mantissa). 
++     *
++     * The current solution is dumb, but it works and uses little code. Use of
++     * integer powers is not anticipated to be very frequent (apart from 2^x,
++     * which is separately optimized).
++     */
++  if (ib==0) *r=0;
++  else if (ic<0) return 0;  /* FP realm */
++  else if (ib==2 && ic < (int)sizeof(lua_Integer)*8-1) *r= ((lua_Integer)1)<<ic;   /* 1,2,4,...2^30 | 2^62 optimization */
++  else if (ic==0) *r=1;
++  else if (luai_abs(ib)==1) *r= (ic%2) ? ib:1;
++  else {
++    lua_Integer x= ib;
++    while( --ic ) {
++      if (!try_mulint( &x, x, ib ))
++        return 0; /* FP realm */
++    }
++    *r= x;
++  }
++  return 1;
++}
++
++int try_unmint( lua_Integer *r, lua_Integer ib ) {
++  /* Negating LUA_INTEGER_MIN leaves the range. */
++  if ( ib != LUA_INTEGER_MIN )  
++    { *r= -ib; return 1; }
++  return 0;
++}
++
+--- /dev/null
++++ b/src/lnum.h
+@@ -0,0 +1,116 @@
++/*
++** $Id: lnum.h,v ... $
++** Internal Number model
++** See Copyright Notice in lua.h
++*/
++
++#ifndef lnum_h
++#define lnum_h
++
++#include <math.h>
++
++#include "lobject.h"
++
++/*
++** The luai_num* macros define the primitive operations over 'lua_Number's
++** (not 'lua_Integer's, not 'lua_Complex').
++*/
++#define luai_numadd(a,b)	((a)+(b))
++#define luai_numsub(a,b)	((a)-(b))
++#define luai_nummul(a,b)	((a)*(b))
++#define luai_numdiv(a,b)	((a)/(b))
++#define luai_nummod(a,b)	((a) - _LF(floor)((a)/(b))*(b))
++#define luai_numpow(a,b)	(_LF(pow)(a,b))
++#define luai_numunm(a)		(-(a))
++#define luai_numeq(a,b)	    ((a)==(b))
++#define luai_numlt(a,b)	    ((a)<(b))
++#define luai_numle(a,b)	    ((a)<=(b))
++#define luai_numisnan(a)	(!luai_numeq((a), (a)))
++
++int try_addint( lua_Integer *r, lua_Integer ib, lua_Integer ic );
++int try_subint( lua_Integer *r, lua_Integer ib, lua_Integer ic );
++int try_mulint( lua_Integer *r, lua_Integer ib, lua_Integer ic );
++int try_divint( lua_Integer *r, lua_Integer ib, lua_Integer ic );
++int try_modint( lua_Integer *r, lua_Integer ib, lua_Integer ic );
++int try_powint( lua_Integer *r, lua_Integer ib, lua_Integer ic );
++int try_unmint( lua_Integer *r, lua_Integer ib );
++
++#ifdef LNUM_COMPLEX
++  static inline lua_Complex luai_vectunm( lua_Complex a ) { return -a; }
++  static inline lua_Complex luai_vectadd( lua_Complex a, lua_Complex b ) { return a+b; }
++  static inline lua_Complex luai_vectsub( lua_Complex a, lua_Complex b ) { return a-b; }
++  static inline lua_Complex luai_vectmul( lua_Complex a, lua_Complex b ) { return a*b; }
++  static inline lua_Complex luai_vectdiv( lua_Complex a, lua_Complex b ) { return a/b; }
++
++/* 
++ * C99 does not provide modulus for complex numbers. It most likely is not
++ * meaningful at all.
++ */
++
++/* 
++ * Complex power
++ *
++ * C99 'cpow' gives inaccurate results for many common cases s.a. (1i)^2 -> 
++ * -1+1.2246467991474e-16i (OS X 10.4, gcc 4.0.1 build 5367)
++ * 
++ * [(a+bi)^(c+di)] = (r^c) * exp(-d*t) * cos(c*t + d*ln(r)) +
++ *                 = (r^c) * exp(-d*t) * sin(c*t + d*ln(r)) *i
++ * r = sqrt(a^2+b^2), t = arctan( b/a )
++ * 
++ * Reference: <http://home.att.net/~srschmitt/complexnumbers.html>
++ * Could also be calculated using: x^y = exp(ln(x)*y)
++ *
++ * Note: Defined here (and not in .c) so 'lmathlib.c' can share the 
++ *       implementation.
++ */
++  static inline
++  lua_Complex luai_vectpow( lua_Complex a, lua_Complex b )
++  {
++# if 1
++    lua_Number ar= _LF(creal)(a), ai= _LF(cimag)(a);
++    lua_Number br= _LF(creal)(b), bi= _LF(cimag)(b);
++    
++    if (ai==0 && bi==0) {     /* a^c (real) */
++        return luai_numpow( ar, br );
++    } 
++
++    int br_int= (int)br;
++    
++    if ( ai!=0 && bi==0 && br_int==br && br_int!=0 && br_int!=INT_MIN ) { 
++        /* (a+bi)^N, N = { +-1,+-2, ... +-INT_MAX } 
++        */
++        lua_Number k= luai_numpow( _LF(sqrt) (ar*ar + ai*ai), br );
++        lua_Number cos_z, sin_z;
++
++        /* Situation depends upon c (N) in the following manner:
++         * 
++         * N%4==0                                => cos(c*t)=1, sin(c*t)=0
++         * (N*sign(b))%4==1 or (N*sign(b))%4==-3 => cos(c*t)=0, sin(c*t)=1
++         * N%4==2 or N%4==-2                     => cos(c*t)=-1, sin(c*t)=0
++         * (N*sign(b))%4==-1 or (N*sign(b))%4==3 => cos(c*t)=0, sin(c*t)=-1
++         */
++      int br_int_abs = br_int<0 ? -br_int:br_int;
++      
++      switch( (br_int_abs%4) * (br_int<0 ? -1:1) * (ai<0 ? -1:1) ) {
++        case 0:             cos_z=1, sin_z=0; break;
++        case 2: case -2:    cos_z=-1, sin_z=0; break;
++        case 1: case -3:    cos_z=0, sin_z=1; break;
++        case 3: case -1:    cos_z=0, sin_z=-1; break;
++        default:            lua_assert(0); return 0;
++      }
++      return k*cos_z + (k*sin_z)*I;
++    }
++# endif
++    return _LF(cpow) ( a, b );
++  }
++#endif
++
++LUAI_FUNC int luaO_str2d (const char *s, lua_Number *res1, lua_Integer *res2);
++LUAI_FUNC void luaO_num2buf( char *s, const TValue *o );
++
++LUAI_FUNC int /*bool*/ tt_integer_valued( const TValue *o, lua_Integer *ref );
++
++#define luai_normalize(o) \
++{ lua_Integer _i; if (tt_integer_valued(o,&_i)) setivalue(o,_i); }
++
++#endif
+--- /dev/null
++++ b/src/lnum_config.h
+@@ -0,0 +1,221 @@
++/*
++** $Id: lnum_config.h,v ... $
++** Internal Number model
++** See Copyright Notice in lua.h
++*/
++
++#ifndef lnum_config_h
++#define lnum_config_h
++
++/*
++** Default number modes
++*/
++#if (!defined LNUM_DOUBLE) && (!defined LNUM_FLOAT) && (!defined LNUM_LDOUBLE)
++# define LNUM_FLOAT
++#endif
++#if (!defined LNUM_INT16) && (!defined LNUM_INT32) && (!defined LNUM_INT64)
++# define LNUM_INT32
++#endif
++
++/*
++** Require C99 mode for COMPLEX, FLOAT and LDOUBLE (only DOUBLE is ANSI C).
++*/
++#if defined(LNUM_COMPLEX) && (__STDC_VERSION__ < 199901L)
++# error "Need C99 for complex (use '--std=c99' or similar)"
++#elif defined(LNUM_LDOUBLE) && (__STDC_VERSION__ < 199901L) && !defined(_MSC_VER)
++# error "Need C99 for 'long double' (use '--std=c99' or similar)"
++#elif defined(LNUM_FLOAT) && (__STDC_VERSION__ < 199901L)
++/* LNUM_FLOAT not supported on Windows */
++# error "Need C99 for 'float' (use '--std=c99' or similar)"
++#endif
++ 
++/*
++** Number mode identifier to accompany the version string.
++*/
++#ifdef LNUM_COMPLEX
++# define _LNUM1 "complex "
++#else
++# define _LNUM1 ""
++#endif
++#ifdef LNUM_DOUBLE
++# define _LNUM2 "double"
++#elif defined(LNUM_FLOAT)
++# define _LNUM2 "float"
++#elif defined(LNUM_LDOUBLE)
++# define _LNUM2 "ldouble"
++#endif
++#ifdef LNUM_INT32
++# define _LNUM3 "int32"
++#elif defined(LNUM_INT64)
++# define _LNUM3 "int64"
++#elif defined(LNUM_INT16)
++# define _LNUM3 "int16"
++#endif
++#define LUA_LNUM _LNUM1 _LNUM2 " " _LNUM3
++
++/*
++** LUA_NUMBER is the type of floating point number in Lua
++** LUA_NUMBER_SCAN is the format for reading numbers.
++** LUA_NUMBER_FMT is the format for writing numbers.
++*/
++#ifdef LNUM_FLOAT
++# define LUA_NUMBER         float
++# define LUA_NUMBER_SCAN    "%f"
++# define LUA_NUMBER_FMT     "%g"  
++#elif (defined LNUM_DOUBLE)
++# define LUA_NUMBER	        double
++# define LUA_NUMBER_SCAN    "%lf"
++# define LUA_NUMBER_FMT     "%.14g"
++#elif (defined LNUM_LDOUBLE)
++# define LUA_NUMBER         long double
++# define LUA_NUMBER_SCAN    "%Lg"
++# define LUA_NUMBER_FMT     "%.20Lg"
++#endif
++
++
++/* 
++** LUAI_MAXNUMBER2STR: size of a buffer fitting any number->string result.
++**
++**  double:  24 (sign, x.xxxxxxxxxxxxxxe+nnnn, and \0)
++**  int64:   21 (19 digits, sign, and \0)
++**  long double: 43 for 128-bit (sign, x.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxe+nnnn, and \0)
++**           30 for 80-bit (sign, x.xxxxxxxxxxxxxxxxxxxxe+nnnn, and \0)
++*/
++#ifdef LNUM_LDOUBLE
++# define _LUAI_MN2S 44
++#else
++# define _LUAI_MN2S 24
++#endif
++
++#ifdef LNUM_COMPLEX
++# define LUAI_MAXNUMBER2STR (2*_LUAI_MN2S)
++#else
++# define LUAI_MAXNUMBER2STR _LUAI_MN2S
++#endif
++
++/*
++** LUA_INTEGER is the integer type used by lua_pushinteger/lua_tointeger/lua_isinteger.
++** LUA_INTEGER_SCAN is the format for reading integers
++** LUA_INTEGER_FMT is the format for writing integers
++**
++** Note: Visual C++ 2005 does not have 'strtoull()', use '_strtoui64()' instead.
++*/
++#ifdef LNUM_INT32
++# if LUAI_BITSINT > 16
++#  define LUA_INTEGER   int
++#  define LUA_INTEGER_SCAN "%d"
++#  define LUA_INTEGER_FMT "%d"
++# else
++/* Note: 'LUA_INTEGER' being 'ptrdiff_t' (as in Lua 5.1) causes problems with
++ *       'printf()' operations. Also 'unsigned ptrdiff_t' is invalid.
++ */
++#  define LUA_INTEGER   long
++#  define LUA_INTEGER_SCAN "%ld"
++#  define LUA_INTEGER_FMT "%ld"
++# endif
++# define LUA_INTEGER_MAX 0x7FFFFFFF             /* 2^31-1 */
++/* */
++#elif defined(LNUM_INT64)
++# define LUA_INTEGER	long long
++# ifdef _MSC_VER
++#  define lua_str2ul    _strtoui64
++# else
++#  define lua_str2ul    strtoull
++# endif
++# define LUA_INTEGER_SCAN "%lld"
++# define LUA_INTEGER_FMT "%lld"
++# define LUA_INTEGER_MAX 0x7fffffffffffffffLL       /* 2^63-1 */ 
++# define LUA_INTEGER_MIN (-LUA_INTEGER_MAX - 1LL)   /* -2^63 */
++/* */
++#elif defined(LNUM_INT16)
++# if LUAI_BITSINT > 16
++#  define LUA_INTEGER    short
++#  define LUA_INTEGER_SCAN "%hd"
++#  define LUA_INTEGER_FMT "%hd"
++# else
++#  define LUA_INTEGER    int
++#  define LUA_INTEGER_SCAN "%d"
++#  define LUA_INTEGER_FMT "%d"
++# endif
++# define LUA_INTEGER_MAX 0x7FFF             /* 2^16-1 */
++#endif
++
++#ifndef lua_str2ul
++# define lua_str2ul (unsigned LUA_INTEGER)strtoul
++#endif
++#ifndef LUA_INTEGER_MIN
++# define LUA_INTEGER_MIN (-LUA_INTEGER_MAX -1)  /* -2^16|32 */
++#endif
++
++/*
++@@ lua_number2int is a macro to convert lua_Number to int.
++@@ lua_number2integer is a macro to convert lua_Number to lua_Integer.
++** CHANGE them if you know a faster way to convert a lua_Number to
++** int (with any rounding method and without throwing errors) in your
++** system. In Pentium machines, a naive typecast from double to int
++** in C is extremely slow, so any alternative is worth trying.
++*/
++
++/* On a Pentium, resort to a trick */
++#if defined(LNUM_DOUBLE) && !defined(LUA_ANSI) && !defined(__SSE2__) && \
++    (defined(__i386) || defined (_M_IX86) || defined(__i386__))
++
++/* On a Microsoft compiler, use assembler */
++# if defined(_MSC_VER)
++#  define lua_number2int(i,d)   __asm fld d   __asm fistp i
++# else
++
++/* the next trick should work on any Pentium, but sometimes clashes
++   with a DirectX idiosyncrasy */
++union luai_Cast { double l_d; long l_l; };
++#  define lua_number2int(i,d) \
++  { volatile union luai_Cast u; u.l_d = (d) + 6755399441055744.0; (i) = u.l_l; }
++# endif
++
++# ifndef LNUM_INT64
++#  define lua_number2integer    lua_number2int
++# endif
++
++/* this option always works, but may be slow */
++#else
++# define lua_number2int(i,d)        ((i)=(int)(d))
++#endif
++
++/* Note: Some compilers (OS X gcc 4.0?) may choke on double->long long conversion 
++ *       since it can lose precision. Others do require 'long long' there.  
++ */
++#ifndef lua_number2integer
++# define lua_number2integer(i,d)    ((i)=(lua_Integer)(d))
++#endif
++
++/*
++** 'luai_abs()' to give absolute value of 'lua_Integer'
++*/
++#ifdef LNUM_INT32
++# define luai_abs abs
++#elif defined(LNUM_INT64) && (__STDC_VERSION__ >= 199901L)
++# define luai_abs llabs
++#else
++# define luai_abs(v) ((v) >= 0 ? (v) : -(v))
++#endif
++
++/*
++** LUAI_UACNUMBER is the result of an 'usual argument conversion' over a number.
++** LUAI_UACINTEGER the same, over an integer.
++*/
++#define LUAI_UACNUMBER	double
++#define LUAI_UACINTEGER long
++
++/* ANSI C only has math funcs for 'double. C99 required for float and long double
++ * variants.
++ */
++#ifdef LNUM_DOUBLE
++# define _LF(name) name
++#elif defined(LNUM_FLOAT)
++# define _LF(name) name ## f
++#elif defined(LNUM_LDOUBLE)
++# define _LF(name) name ## l
++#endif
++
++#endif
++
+--- a/src/lobject.c
++++ b/src/lobject.c
+@@ -21,7 +21,8 @@
+ #include "lstate.h"
+ #include "lstring.h"
+ #include "lvm.h"
+-
++#include "llex.h"
++#include "lnum.h"
+ 
+ 
+ const TValue luaO_nilobject_ = {{NULL}, LUA_TNIL};
+@@ -70,12 +71,31 @@ int luaO_log2 (unsigned int x) {
+ 
+ 
+ int luaO_rawequalObj (const TValue *t1, const TValue *t2) {
+-  if (ttype(t1) != ttype(t2)) return 0;
++  if (!ttype_ext_same(t1,t2)) return 0;
+   else switch (ttype(t1)) {
+     case LUA_TNIL:
+       return 1;
++    case LUA_TINT:
++      if (ttype(t2)==LUA_TINT)
++        return ivalue(t1) == ivalue(t2);
++      else {  /* t1:int, t2:num */
++#ifdef LNUM_COMPLEX
++        if (nvalue_img_fast(t2) != 0) return 0;
++#endif
++        /* Avoid doing accuracy losing cast, if possible. */
++        lua_Integer tmp;
++        if (tt_integer_valued(t2,&tmp)) 
++          return ivalue(t1) == tmp;
++        else
++          return luai_numeq( cast_num(ivalue(t1)), nvalue_fast(t2) );
++        }
+     case LUA_TNUMBER:
+-      return luai_numeq(nvalue(t1), nvalue(t2));
++        if (ttype(t2)==LUA_TINT)
++          return luaO_rawequalObj(t2, t1);  /* swap LUA_TINT to left */
++#ifdef LNUM_COMPLEX
++        if (!luai_numeq(nvalue_img_fast(t1), nvalue_img_fast(t2))) return 0;
++#endif
++        return luai_numeq(nvalue_fast(t1), nvalue_fast(t2));
+     case LUA_TBOOLEAN:
+       return bvalue(t1) == bvalue(t2);  /* boolean true must be 1 !! */
+     case LUA_TLIGHTUSERDATA:
+@@ -86,21 +106,6 @@ int luaO_rawequalObj (const TValue *t1,
+   }
+ }
+ 
+-
+-int luaO_str2d (const char *s, lua_Number *result) {
+-  char *endptr;
+-  *result = lua_str2number(s, &endptr);
+-  if (endptr == s) return 0;  /* conversion failed */
+-  if (*endptr == 'x' || *endptr == 'X')  /* maybe an hexadecimal constant? */
+-    *result = cast_num(strtoul(s, &endptr, 16));
+-  if (*endptr == '\0') return 1;  /* most common case */
+-  while (isspace(cast(unsigned char, *endptr))) endptr++;
+-  if (*endptr != '\0') return 0;  /* invalid trailing characters? */
+-  return 1;
+-}
+-
+-
+-
+ static void pushstr (lua_State *L, const char *str) {
+   setsvalue2s(L, L->top, luaS_new(L, str));
+   incr_top(L);
+@@ -131,7 +136,11 @@ const char *luaO_pushvfstring (lua_State
+         break;
+       }
+       case 'd': {
+-        setnvalue(L->top, cast_num(va_arg(argp, int)));
++        /* This is tricky for 64-bit integers; maybe they even cannot be
++         * supported on all compilers; depends on the conversions applied to
++         * variable argument lists. TBD: test!
++         */
++        setivalue(L->top, (lua_Integer) va_arg(argp, l_uacInteger));
+         incr_top(L);
+         break;
+       }
+@@ -212,3 +221,4 @@ void luaO_chunkid (char *out, const char
+     }
+   }
+ }
++
+--- a/src/lobject.h
++++ b/src/lobject.h
+@@ -17,7 +17,11 @@
+ 
+ 
+ /* tags for values visible from Lua */
+-#define LAST_TAG	LUA_TTHREAD
++#if LUA_TINT > LUA_TTHREAD
++# define LAST_TAG   LUA_TINT
++#else
++# define LAST_TAG	LUA_TTHREAD
++#endif
+ 
+ #define NUM_TAGS	(LAST_TAG+1)
+ 
+@@ -59,7 +63,12 @@ typedef struct GCheader {
+ typedef union {
+   GCObject *gc;
+   void *p;
++#ifdef LNUM_COMPLEX
++  lua_Complex n;
++#else
+   lua_Number n;
++#endif
++  lua_Integer i;
+   int b;
+ } Value;
+ 
+@@ -77,7 +86,11 @@ typedef struct lua_TValue {
+ 
+ /* Macros to test type */
+ #define ttisnil(o)	(ttype(o) == LUA_TNIL)
+-#define ttisnumber(o)	(ttype(o) == LUA_TNUMBER)
++#define ttisint(o) (ttype(o) == LUA_TINT)
++#define ttisnumber(o) ((ttype(o) == LUA_TINT) || (ttype(o) == LUA_TNUMBER))
++#ifdef LNUM_COMPLEX
++# define ttiscomplex(o) ((ttype(o) == LUA_TNUMBER) && (nvalue_img_fast(o)!=0))
++#endif
+ #define ttisstring(o)	(ttype(o) == LUA_TSTRING)
+ #define ttistable(o)	(ttype(o) == LUA_TTABLE)
+ #define ttisfunction(o)	(ttype(o) == LUA_TFUNCTION)
+@@ -90,7 +103,25 @@ typedef struct lua_TValue {
+ #define ttype(o)	((o)->tt)
+ #define gcvalue(o)	check_exp(iscollectable(o), (o)->value.gc)
+ #define pvalue(o)	check_exp(ttislightuserdata(o), (o)->value.p)
+-#define nvalue(o)	check_exp(ttisnumber(o), (o)->value.n)
++
++#define ttype_ext(o) ( ttype(o) == LUA_TINT ? LUA_TNUMBER : ttype(o) )
++#define ttype_ext_same(o1,o2) ( (ttype(o1)==ttype(o2)) || (ttisnumber(o1) && ttisnumber(o2)) )
++
++/* '_fast' variants are for cases where 'ttype(o)' is known to be LUA_TNUMBER.
++ */
++#ifdef LNUM_COMPLEX
++#  define nvalue_complex_fast(o) check_exp( ttype(o)==LUA_TNUMBER, (o)->value.n )   
++#  define nvalue_fast(o)     ( _LF(creal) ( nvalue_complex_fast(o) ) )
++#  define nvalue_img_fast(o) ( _LF(cimag) ( nvalue_complex_fast(o) ) )
++#  define nvalue_complex(o) check_exp( ttisnumber(o), (ttype(o)==LUA_TINT) ? (o)->value.i : (o)->value.n )
++#  define nvalue_img(o) check_exp( ttisnumber(o), (ttype(o)==LUA_TINT) ? 0 : _LF(cimag)( (o)->value.n ) ) 
++#  define nvalue(o) check_exp( ttisnumber(o), (ttype(o)==LUA_TINT) ? cast_num((o)->value.i) : _LF(creal)((o)->value.n) ) 
++#else
++# define nvalue(o)	check_exp( ttisnumber(o), (ttype(o)==LUA_TINT) ? cast_num((o)->value.i) : (o)->value.n )
++# define nvalue_fast(o) check_exp( ttype(o)==LUA_TNUMBER, (o)->value.n )   
++#endif
++#define ivalue(o)	check_exp( ttype(o)==LUA_TINT, (o)->value.i )
++
+ #define rawtsvalue(o)	check_exp(ttisstring(o), &(o)->value.gc->ts)
+ #define tsvalue(o)	(&rawtsvalue(o)->tsv)
+ #define rawuvalue(o)	check_exp(ttisuserdata(o), &(o)->value.gc->u)
+@@ -116,8 +147,27 @@ typedef struct lua_TValue {
+ /* Macros to set values */
+ #define setnilvalue(obj) ((obj)->tt=LUA_TNIL)
+ 
+-#define setnvalue(obj,x) \
+-  { TValue *i_o=(obj); i_o->value.n=(x); i_o->tt=LUA_TNUMBER; }
++/* Must not have side effects, 'x' may be expression.
++*/
++#define setivalue(obj,x) \
++    { TValue *i_o=(obj); i_o->value.i=(x); i_o->tt=LUA_TINT; }
++
++# define setnvalue(obj,x) \
++    { TValue *i_o=(obj); i_o->value.n= (x); i_o->tt=LUA_TNUMBER; }
++
++/* Note: Complex always has "inline", both are C99.
++*/
++#ifdef LNUM_COMPLEX
++  static inline void setnvalue_complex_fast( TValue *obj, lua_Complex x ) {
++    lua_assert( _LF(cimag)(x) != 0 );
++    obj->value.n= x; obj->tt= LUA_TNUMBER;
++  }
++  static inline void setnvalue_complex( TValue *obj, lua_Complex x ) {
++    if (_LF(cimag)(x) == 0) { setnvalue(obj, _LF(creal)(x)); }
++    else { obj->value.n= x; obj->tt= LUA_TNUMBER; }
++  }
++#endif
++
+ 
+ #define setpvalue(obj,x) \
+   { TValue *i_o=(obj); i_o->value.p=(x); i_o->tt=LUA_TLIGHTUSERDATA; }
+@@ -155,9 +205,6 @@ typedef struct lua_TValue {
+     i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TPROTO; \
+     checkliveness(G(L),i_o); }
+ 
+-
+-
+-
+ #define setobj(L,obj1,obj2) \
+   { const TValue *o2=(obj2); TValue *o1=(obj1); \
+     o1->value = o2->value; o1->tt=o2->tt; \
+@@ -185,8 +232,11 @@ typedef struct lua_TValue {
+ 
+ #define setttype(obj, tt) (ttype(obj) = (tt))
+ 
+-
+-#define iscollectable(o)	(ttype(o) >= LUA_TSTRING)
++#if LUA_TINT >= LUA_TSTRING
++# define iscollectable(o)	((ttype(o) >= LUA_TSTRING) && (ttype(o) != LUA_TINT))
++#else
++# define iscollectable(o)	(ttype(o) >= LUA_TSTRING)
++#endif
+ 
+ 
+ 
+@@ -370,12 +420,10 @@ LUAI_FUNC int luaO_log2 (unsigned int x)
+ LUAI_FUNC int luaO_int2fb (unsigned int x);
+ LUAI_FUNC int luaO_fb2int (int x);
+ LUAI_FUNC int luaO_rawequalObj (const TValue *t1, const TValue *t2);
+-LUAI_FUNC int luaO_str2d (const char *s, lua_Number *result);
+ LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt,
+                                                        va_list argp);
+ LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...);
+ LUAI_FUNC void luaO_chunkid (char *out, const char *source, size_t len);
+ 
+-
+ #endif
+ 
+--- a/src/loslib.c
++++ b/src/loslib.c
+@@ -186,15 +186,30 @@ static int os_time (lua_State *L) {
+   }
+   if (t == (time_t)(-1))
+     lua_pushnil(L);
+-  else
+-    lua_pushnumber(L, (lua_Number)t);
++  else {
++     /* On float systems the pushed value must be an integer, NOT a number.
++      * Otherwise, accuracy is lost in the time_t->float conversion.
++      */
++#ifdef LNUM_FLOAT
++     lua_pushinteger(L, (lua_Integer) t);
++#else
++     lua_pushnumber(L, (lua_Number) t);
++#endif
++     }
+   return 1;
+ }
+ 
+ 
+ static int os_difftime (lua_State *L) {
++#ifdef LNUM_FLOAT
++  lua_Integer i= (lua_Integer)
++    difftime( (time_t)(luaL_checkinteger(L, 1)),
++              (time_t)(luaL_optinteger(L, 2, 0)));
++  lua_pushinteger(L, i);
++#else
+   lua_pushnumber(L, difftime((time_t)(luaL_checknumber(L, 1)),
+                              (time_t)(luaL_optnumber(L, 2, 0))));
++#endif
+   return 1;
+ }
+ 
+--- a/src/lparser.c
++++ b/src/lparser.c
+@@ -33,7 +33,6 @@
+ 
+ #define luaY_checklimit(fs,v,l,m)	if ((v)>(l)) errorlimit(fs,l,m)
+ 
+-
+ /*
+ ** nodes for block list (list of active blocks)
+ */
+@@ -72,7 +71,7 @@ static void errorlimit (FuncState *fs, i
+   const char *msg = (fs->f->linedefined == 0) ?
+     luaO_pushfstring(fs->L, "main function has more than %d %s", limit, what) :
+     luaO_pushfstring(fs->L, "function at line %d has more than %d %s",
+-                            fs->f->linedefined, limit, what);
++                            (fs->f->linedefined), limit, what);
+   luaX_lexerror(fs->ls, msg, 0);
+ }
+ 
+@@ -733,6 +732,18 @@ static void simpleexp (LexState *ls, exp
+       v->u.nval = ls->t.seminfo.r;
+       break;
+     }
++    case TK_INT: {
++      init_exp(v, VKINT, 0);
++      v->u.ival = ls->t.seminfo.i;
++      break;
++    }
++#ifdef LNUM_COMPLEX
++    case TK_NUMBER2: {
++      init_exp(v, VKNUM2, 0);
++      v->u.nval = ls->t.seminfo.r;
++      break;
++    }
++#endif
+     case TK_STRING: {
+       codestring(ls, v, ls->t.seminfo.ts);
+       break;
+@@ -1079,7 +1090,7 @@ static void fornum (LexState *ls, TStrin
+   if (testnext(ls, ','))
+     exp1(ls);  /* optional step */
+   else {  /* default step = 1 */
+-    luaK_codeABx(fs, OP_LOADK, fs->freereg, luaK_numberK(fs, 1));
++    luaK_codeABx(fs, OP_LOADK, fs->freereg, luaK_integerK(fs, 1));
+     luaK_reserveregs(fs, 1);
+   }
+   forbody(ls, base, line, 1, 1);
+--- a/src/lparser.h
++++ b/src/lparser.h
+@@ -31,7 +31,11 @@ typedef enum {
+   VRELOCABLE,	/* info = instruction pc */
+   VNONRELOC,	/* info = result register */
+   VCALL,	/* info = instruction pc */
+-  VVARARG	/* info = instruction pc */
++  VVARARG,	/* info = instruction pc */
++  VKINT     /* ival = integer value */
++#ifdef LNUM_COMPLEX
++  ,VKNUM2   /* nval = imaginary value */
++#endif
+ } expkind;
+ 
+ typedef struct expdesc {
+@@ -39,6 +43,7 @@ typedef struct expdesc {
+   union {
+     struct { int info, aux; } s;
+     lua_Number nval;
++    lua_Integer ival;
+   } u;
+   int t;  /* patch list of `exit when true' */
+   int f;  /* patch list of `exit when false' */
+--- a/src/lstrlib.c
++++ b/src/lstrlib.c
+@@ -43,8 +43,8 @@ static ptrdiff_t posrelat (ptrdiff_t pos
+ static int str_sub (lua_State *L) {
+   size_t l;
+   const char *s = luaL_checklstring(L, 1, &l);
+-  ptrdiff_t start = posrelat(luaL_checkinteger(L, 2), l);
+-  ptrdiff_t end = posrelat(luaL_optinteger(L, 3, -1), l);
++  ptrdiff_t start = posrelat(luaL_checkint32(L, 2), l);
++  ptrdiff_t end = posrelat(luaL_optint32(L, 3, -1), l);
+   if (start < 1) start = 1;
+   if (end > (ptrdiff_t)l) end = (ptrdiff_t)l;
+   if (start <= end)
+@@ -106,8 +106,8 @@ static int str_rep (lua_State *L) {
+ static int str_byte (lua_State *L) {
+   size_t l;
+   const char *s = luaL_checklstring(L, 1, &l);
+-  ptrdiff_t posi = posrelat(luaL_optinteger(L, 2, 1), l);
+-  ptrdiff_t pose = posrelat(luaL_optinteger(L, 3, posi), l);
++  ptrdiff_t posi = posrelat(luaL_optint32(L, 2, 1), l);
++  ptrdiff_t pose = posrelat(luaL_optint32(L, 3, posi), l);
+   int n, i;
+   if (posi <= 0) posi = 1;
+   if ((size_t)pose > l) pose = l;
+@@ -496,7 +496,7 @@ static int str_find_aux (lua_State *L, i
+   size_t l1, l2;
+   const char *s = luaL_checklstring(L, 1, &l1);
+   const char *p = luaL_checklstring(L, 2, &l2);
+-  ptrdiff_t init = posrelat(luaL_optinteger(L, 3, 1), l1) - 1;
++  ptrdiff_t init = posrelat(luaL_optint32(L, 3, 1), l1) - 1;
+   if (init < 0) init = 0;
+   else if ((size_t)(init) > l1) init = (ptrdiff_t)l1;
+   if (find && (lua_toboolean(L, 4) ||  /* explicit request? */
+@@ -690,7 +690,7 @@ static int str_gsub (lua_State *L) {
+ ** maximum size of each format specification (such as '%-099.99d')
+ ** (+10 accounts for %99.99x plus margin of error)
+ */
+-#define MAX_FORMAT	(sizeof(FLAGS) + sizeof(LUA_INTFRMLEN) + 10)
++#define MAX_FORMAT	(sizeof(FLAGS) + sizeof(LUA_INTEGER_FMT)-2 + 10)
+ 
+ 
+ static void addquoted (lua_State *L, luaL_Buffer *b, int arg) {
+@@ -747,9 +747,9 @@ static const char *scanformat (lua_State
+ static void addintlen (char *form) {
+   size_t l = strlen(form);
+   char spec = form[l - 1];
+-  strcpy(form + l - 1, LUA_INTFRMLEN);
+-  form[l + sizeof(LUA_INTFRMLEN) - 2] = spec;
+-  form[l + sizeof(LUA_INTFRMLEN) - 1] = '\0';
++  const char *tmp= LUA_INTEGER_FMT;   /* "%lld" or "%ld" */
++  strcpy(form + l - 1, tmp+1);
++  form[l + sizeof(LUA_INTEGER_FMT)-4] = spec;
+ }
+ 
+ 
+@@ -779,12 +779,12 @@ static int str_format (lua_State *L) {
+         }
+         case 'd':  case 'i': {
+           addintlen(form);
+-          sprintf(buff, form, (LUA_INTFRM_T)luaL_checknumber(L, arg));
++          sprintf(buff, form, luaL_checkinteger(L, arg));
+           break;
+         }
+         case 'o':  case 'u':  case 'x':  case 'X': {
+           addintlen(form);
+-          sprintf(buff, form, (unsigned LUA_INTFRM_T)luaL_checknumber(L, arg));
++          sprintf(buff, form, (unsigned LUA_INTEGER)luaL_checkinteger(L, arg));
+           break;
+         }
+         case 'e':  case 'E': case 'f':
+--- a/src/ltable.c
++++ b/src/ltable.c
+@@ -33,6 +33,7 @@
+ #include "lobject.h"
+ #include "lstate.h"
+ #include "ltable.h"
++#include "lnum.h"
+ 
+ 
+ /*
+@@ -51,25 +52,15 @@
+   
+ #define hashstr(t,str)  hashpow2(t, (str)->tsv.hash)
+ #define hashboolean(t,p)        hashpow2(t, p)
+-
++#define hashint(t,i)    hashpow2(t,i)
+ 
+ /*
+ ** for some types, it is better to avoid modulus by power of 2, as
+ ** they tend to have many 2 factors.
+ */
+ #define hashmod(t,n)	(gnode(t, ((n) % ((sizenode(t)-1)|1))))
+-
+-
+ #define hashpointer(t,p)	hashmod(t, IntPoint(p))
+ 
+-
+-/*
+-** number of ints inside a lua_Number
+-*/
+-#define numints		cast_int(sizeof(lua_Number)/sizeof(int))
+-
+-
+-
+ #define dummynode		(&dummynode_)
+ 
+ static const Node dummynode_ = {
+@@ -80,27 +71,46 @@ static const Node dummynode_ = {
+ 
+ /*
+ ** hash for lua_Numbers
++**
++** for non-complex modes, never called with 'lua_Integer' value range (s.a. 0)
+ */
+ static Node *hashnum (const Table *t, lua_Number n) {
+-  unsigned int a[numints];
+-  int i;
+-  if (luai_numeq(n, 0))  /* avoid problems with -0 */
+-    return gnode(t, 0);
+-  memcpy(a, &n, sizeof(a));
+-  for (i = 1; i < numints; i++) a[0] += a[i];
+-  return hashmod(t, a[0]);
++  const unsigned int *p= cast(const unsigned int *,&n);
++  unsigned int sum= *p;
++  unsigned int m= sizeof(lua_Number)/sizeof(int);
++  unsigned int i;
++  /* OS X Intel has 'm'==4 and gives "Bus error" if the last integer of 
++   * 'n' is read; the actual size of long double is only 80 bits = 10 bytes.
++   * Linux x86 has 'm'==3, and does not require reduction.
++   */
++#if defined(LNUM_LDOUBLE) && defined(__i386__)
++  if (m>3) m--;
++#endif
++  for (i = 1; i < m; i++) sum += p[i];
++  return hashmod(t, sum);
+ }
+ 
+ 
+-
+ /*
+ ** returns the `main' position of an element in a table (that is, the index
+ ** of its hash value)
++**
++** Floating point numbers with integer value give the hash position of the
++** integer (so they use the same table position).
+ */
+ static Node *mainposition (const Table *t, const TValue *key) {
++  lua_Integer i;
+   switch (ttype(key)) {
+     case LUA_TNUMBER:
+-      return hashnum(t, nvalue(key));
++      if (tt_integer_valued(key,&i)) 
++        return hashint(t, i);
++#ifdef LNUM_COMPLEX
++      if (nvalue_img_fast(key)!=0 && luai_numeq(nvalue_fast(key),0))
++        return gnode(t, 0);  /* 0 and -0 to give same hash */
++#endif
++      return hashnum(t, nvalue_fast(key));
++    case LUA_TINT:
++      return hashint(t, ivalue(key));
+     case LUA_TSTRING:
+       return hashstr(t, rawtsvalue(key));
+     case LUA_TBOOLEAN:
+@@ -116,16 +126,20 @@ static Node *mainposition (const Table *
+ /*
+ ** returns the index for `key' if `key' is an appropriate key to live in
+ ** the array part of the table, -1 otherwise.
++**
++** Anything <=0 is taken as not being in the array part.
+ */
+-static int arrayindex (const TValue *key) {
+-  if (ttisnumber(key)) {
+-    lua_Number n = nvalue(key);
+-    int k;
+-    lua_number2int(k, n);
+-    if (luai_numeq(cast_num(k), n))
+-      return k;
++static int arrayindex (const TValue *key, int max) {
++  lua_Integer k;
++  switch( ttype(key) ) {
++    case LUA_TINT:
++      k= ivalue(key); break;
++    case LUA_TNUMBER:
++      if (tt_integer_valued(key,&k)) break;
++    default:
++      return -1;  /* not to be used as array index */
+   }
+-  return -1;  /* `key' did not match some condition */
++  return ((k>0) && (k <= max)) ? cast_int(k) : -1;
+ }
+ 
+ 
+@@ -137,8 +151,8 @@ static int arrayindex (const TValue *key
+ static int findindex (lua_State *L, Table *t, StkId key) {
+   int i;
+   if (ttisnil(key)) return -1;  /* first iteration */
+-  i = arrayindex(key);
+-  if (0 < i && i <= t->sizearray)  /* is `key' inside array part? */
++  i = arrayindex(key, t->sizearray);
++  if (i>0)  /* inside array part? */
+     return i-1;  /* yes; that's the index (corrected to C) */
+   else {
+     Node *n = mainposition(t, key);
+@@ -163,7 +177,7 @@ int luaH_next (lua_State *L, Table *t, S
+   int i = findindex(L, t, key);  /* find original element */
+   for (i++; i < t->sizearray; i++) {  /* try first array part */
+     if (!ttisnil(&t->array[i])) {  /* a non-nil value? */
+-      setnvalue(key, cast_num(i+1));
++      setivalue(key, i+1);
+       setobj2s(L, key+1, &t->array[i]);
+       return 1;
+     }
+@@ -209,8 +223,8 @@ static int computesizes (int nums[], int
+ 
+ 
+ static int countint (const TValue *key, int *nums) {
+-  int k = arrayindex(key);
+-  if (0 < k && k <= MAXASIZE) {  /* is `key' an appropriate array index? */
++  int k = arrayindex(key,MAXASIZE);
++  if (k>0) {  /* appropriate array index? */
+     nums[ceillog2(k)]++;  /* count as such */
+     return 1;
+   }
+@@ -308,7 +322,7 @@ static void resize (lua_State *L, Table
+     /* re-insert elements from vanishing slice */
+     for (i=nasize; i<oldasize; i++) {
+       if (!ttisnil(&t->array[i]))
+-        setobjt2t(L, luaH_setnum(L, t, i+1), &t->array[i]);
++        setobjt2t(L, luaH_setint(L, t, i+1), &t->array[i]);
+     }
+     /* shrink array */
+     luaM_reallocvector(L, t->array, oldasize, nasize, TValue);
+@@ -409,7 +423,9 @@ static TValue *newkey (lua_State *L, Tab
+     othern = mainposition(t, key2tval(mp));
+     if (othern != mp) {  /* is colliding node out of its main position? */
+       /* yes; move colliding node into free position */
+-      while (gnext(othern) != mp) othern = gnext(othern);  /* find previous */
++      while (gnext(othern) != mp) {
++        othern = gnext(othern);  /* find previous */
++      }
+       gnext(othern) = n;  /* redo the chain with `n' in place of `mp' */
+       *n = *mp;  /* copy colliding node into free pos. (mp->next also goes) */
+       gnext(mp) = NULL;  /* now `mp' is free */
+@@ -432,17 +448,18 @@ static TValue *newkey (lua_State *L, Tab
+ /*
+ ** search function for integers
+ */
+-const TValue *luaH_getnum (Table *t, int key) {
++const TValue *luaH_getint (Table *t, lua_Integer key) {
+   /* (1 <= key && key <= t->sizearray) */
+   if (cast(unsigned int, key-1) < cast(unsigned int, t->sizearray))
+     return &t->array[key-1];
+   else {
+-    lua_Number nk = cast_num(key);
+-    Node *n = hashnum(t, nk);
++    Node *n = hashint(t, key);
+     do {  /* check whether `key' is somewhere in the chain */
+-      if (ttisnumber(gkey(n)) && luai_numeq(nvalue(gkey(n)), nk))
++      if (ttisint(gkey(n)) && (ivalue(gkey(n)) == key)) {
+         return gval(n);  /* that's it */
+-      else n = gnext(n);
++      } else { 
++      n = gnext(n);
++    }
+     } while (n);
+     return luaO_nilobject;
+   }
+@@ -470,14 +487,12 @@ const TValue *luaH_get (Table *t, const
+   switch (ttype(key)) {
+     case LUA_TNIL: return luaO_nilobject;
+     case LUA_TSTRING: return luaH_getstr(t, rawtsvalue(key));
++    case LUA_TINT: return luaH_getint(t, ivalue(key));
+     case LUA_TNUMBER: {
+-      int k;
+-      lua_Number n = nvalue(key);
+-      lua_number2int(k, n);
+-      if (luai_numeq(cast_num(k), nvalue(key))) /* index is int? */
+-        return luaH_getnum(t, k);  /* use specialized version */
+-      /* else go through */
+-    }
++      lua_Integer i;
++      if (tt_integer_valued(key,&i))
++        return luaH_getint(t,i);
++    } /* pass through */
+     default: {
+       Node *n = mainposition(t, key);
+       do {  /* check whether `key' is somewhere in the chain */
+@@ -498,20 +513,25 @@ TValue *luaH_set (lua_State *L, Table *t
+     return cast(TValue *, p);
+   else {
+     if (ttisnil(key)) luaG_runerror(L, "table index is nil");
+-    else if (ttisnumber(key) && luai_numisnan(nvalue(key)))
+-      luaG_runerror(L, "table index is NaN");
++    else if (ttype(key)==LUA_TNUMBER) {
++      lua_Integer k;
++      if (luai_numisnan(nvalue_fast(key)))
++        luaG_runerror(L, "table index is NaN");
++      if (tt_integer_valued(key,&k))
++        return luaH_setint(L, t, k);
++    }
+     return newkey(L, t, key);
+   }
+ }
+ 
+ 
+-TValue *luaH_setnum (lua_State *L, Table *t, int key) {
+-  const TValue *p = luaH_getnum(t, key);
++TValue *luaH_setint (lua_State *L, Table *t, lua_Integer key) {
++  const TValue *p = luaH_getint(t, key);
+   if (p != luaO_nilobject)
+     return cast(TValue *, p);
+   else {
+     TValue k;
+-    setnvalue(&k, cast_num(key));
++    setivalue(&k, key);
+     return newkey(L, t, &k);
+   }
+ }
+@@ -533,20 +553,21 @@ static int unbound_search (Table *t, uns
+   unsigned int i = j;  /* i is zero or a present index */
+   j++;
+   /* find `i' and `j' such that i is present and j is not */
+-  while (!ttisnil(luaH_getnum(t, j))) {
++  while (!ttisnil(luaH_getint(t, j))) {
+     i = j;
+     j *= 2;
+     if (j > cast(unsigned int, MAX_INT)) {  /* overflow? */
+       /* table was built with bad purposes: resort to linear search */
+-      i = 1;
+-      while (!ttisnil(luaH_getnum(t, i))) i++;
+-      return i - 1;
++      for( i = 1; i<MAX_INT+1; i++ ) {
++        if (ttisnil(luaH_getint(t, i))) break;
++      }
++      return i - 1;  /* up to MAX_INT */
+     }
+   }
+   /* now do a binary search between them */
+   while (j - i > 1) {
+     unsigned int m = (i+j)/2;
+-    if (ttisnil(luaH_getnum(t, m))) j = m;
++    if (ttisnil(luaH_getint(t, m))) j = m;
+     else i = m;
+   }
+   return i;
+--- a/src/ltable.h
++++ b/src/ltable.h
+@@ -18,8 +18,8 @@
+ #define key2tval(n)	(&(n)->i_key.tvk)
+ 
+ 
+-LUAI_FUNC const TValue *luaH_getnum (Table *t, int key);
+-LUAI_FUNC TValue *luaH_setnum (lua_State *L, Table *t, int key);
++LUAI_FUNC const TValue *luaH_getint (Table *t, lua_Integer key);
++LUAI_FUNC TValue *luaH_setint (lua_State *L, Table *t, lua_Integer key);
+ LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key);
+ LUAI_FUNC TValue *luaH_setstr (lua_State *L, Table *t, TString *key);
+ LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key);
+--- a/src/ltm.c
++++ b/src/ltm.c
+@@ -19,7 +19,6 @@
+ #include "ltm.h"
+ 
+ 
+-
+ const char *const luaT_typenames[] = {
+   "nil", "boolean", "userdata", "number",
+   "string", "table", "function", "userdata", "thread",
+@@ -67,6 +66,9 @@ const TValue *luaT_gettmbyobj (lua_State
+     case LUA_TUSERDATA:
+       mt = uvalue(o)->metatable;
+       break;
++    case LUA_TINT:
++      mt = G(L)->mt[LUA_TNUMBER];
++      break;
+     default:
+       mt = G(L)->mt[ttype(o)];
+   }
+--- a/src/lua.c
++++ b/src/lua.c
+@@ -16,7 +16,7 @@
+ 
+ #include "lauxlib.h"
+ #include "lualib.h"
+-
++#include "llimits.h"
+ 
+ 
+ static lua_State *globalL = NULL;
+@@ -382,6 +382,15 @@ int main (int argc, char **argv) {
+     l_message(argv[0], "cannot create state: not enough memory");
+     return EXIT_FAILURE;
+   }
++  /* Checking 'sizeof(lua_Integer)' cannot be made in preprocessor on all compilers.
++  */
++#ifdef LNUM_INT16
++  lua_assert( sizeof(lua_Integer) == 2 );
++#elif defined(LNUM_INT32)
++  lua_assert( sizeof(lua_Integer) == 4 );
++#elif defined(LNUM_INT64)
++  lua_assert( sizeof(lua_Integer) == 8 );
++#endif
+   s.argc = argc;
+   s.argv = argv;
+   status = lua_cpcall(L, &pmain, &s);
+--- a/src/lua.h
++++ b/src/lua.h
+@@ -19,7 +19,7 @@
+ #define LUA_VERSION	"Lua 5.1"
+ #define LUA_RELEASE	"Lua 5.1.5"
+ #define LUA_VERSION_NUM	501
+-#define LUA_COPYRIGHT	"Copyright (C) 1994-2012 Lua.org, PUC-Rio"
++#define LUA_COPYRIGHT	"Copyright (C) 1994-2012 Lua.org, PUC-Rio" " (" LUA_LNUM ")"
+ #define LUA_AUTHORS 	"R. Ierusalimschy, L. H. de Figueiredo & W. Celes"
+ 
+ 
+@@ -71,6 +71,16 @@ typedef void * (*lua_Alloc) (void *ud, v
+ */
+ #define LUA_TNONE		(-1)
+ 
++/* LUA_TINT is an internal type, not visible to applications. There are three
++ * potential values where it can be tweaked to (code autoadjusts to these):
++ *
++ * -2: not 'usual' type value; good since 'LUA_TINT' is not part of the API
++ * LUA_TNUMBER+1: shifts other type values upwards, breaking binary compatibility
++ *     not acceptable for 5.1, maybe 5.2 onwards?
++ *  9: greater than existing (5.1) type values.
++*/
++#define LUA_TINT (-2)
++
+ #define LUA_TNIL		0
+ #define LUA_TBOOLEAN		1
+ #define LUA_TLIGHTUSERDATA	2
+@@ -139,6 +149,8 @@ LUA_API int             (lua_isuserdata)
+ LUA_API int             (lua_type) (lua_State *L, int idx);
+ LUA_API const char     *(lua_typename) (lua_State *L, int tp);
+ 
++LUA_API int             (lua_isinteger) (lua_State *L, int idx);
++
+ LUA_API int            (lua_equal) (lua_State *L, int idx1, int idx2);
+ LUA_API int            (lua_rawequal) (lua_State *L, int idx1, int idx2);
+ LUA_API int            (lua_lessthan) (lua_State *L, int idx1, int idx2);
+@@ -244,6 +256,19 @@ LUA_API lua_Alloc (lua_getallocf) (lua_S
+ LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud);
+ 
+ 
++/*
++* It is unnecessary to break Lua C API 'lua_tonumber()' compatibility, just
++* because the Lua number type is complex. Most C modules would use scalars
++* only. We'll introduce new 'lua_tocomplex' and 'lua_pushcomplex' for when
++* the module really wants to use them.
++*/
++#ifdef LNUM_COMPLEX
++  #include <complex.h>
++  typedef LUA_NUMBER complex lua_Complex;
++  LUA_API lua_Complex (lua_tocomplex) (lua_State *L, int idx);
++  LUA_API void (lua_pushcomplex) (lua_State *L, lua_Complex v);
++#endif
++
+ 
+ /* 
+ ** ===============================================================
+@@ -268,7 +293,12 @@ LUA_API void lua_setallocf (lua_State *L
+ #define lua_isboolean(L,n)	(lua_type(L, (n)) == LUA_TBOOLEAN)
+ #define lua_isthread(L,n)	(lua_type(L, (n)) == LUA_TTHREAD)
+ #define lua_isnone(L,n)		(lua_type(L, (n)) == LUA_TNONE)
+-#define lua_isnoneornil(L, n)	(lua_type(L, (n)) <= 0)
++
++#if LUA_TINT < 0
++# define lua_isnoneornil(L, n)	( (lua_type(L,(n)) <= 0) && (lua_type(L,(n)) != LUA_TINT) )
++#else
++# define lua_isnoneornil(L, n)	(lua_type(L, (n)) <= 0)
++#endif
+ 
+ #define lua_pushliteral(L, s)	\
+ 	lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1)
+@@ -386,3 +416,4 @@ struct lua_Debug {
+ 
+ 
+ #endif
++
+--- a/src/luaconf.h
++++ b/src/luaconf.h
+@@ -10,7 +10,9 @@
+ 
+ #include <limits.h>
+ #include <stddef.h>
+-
++#ifdef lua_assert
++# include <assert.h>
++#endif
+ 
+ /*
+ ** ==================================================================
+@@ -136,14 +138,38 @@
+ 
+ 
+ /*
+-@@ LUA_INTEGER is the integral type used by lua_pushinteger/lua_tointeger.
+-** CHANGE that if ptrdiff_t is not adequate on your machine. (On most
+-** machines, ptrdiff_t gives a good choice between int or long.)
++@@ LUAI_BITSINT defines the number of bits in an int.
++** CHANGE here if Lua cannot automatically detect the number of bits of
++** your machine. Probably you do not need to change this.
+ */
+-#define LUA_INTEGER	ptrdiff_t
++/* avoid overflows in comparison */
++#if INT_MAX-20 < 32760
++#define LUAI_BITSINT	16
++#elif INT_MAX > 2147483640L
++/* int has at least 32 bits */
++#define LUAI_BITSINT	32
++#else
++#error "you must define LUA_BITSINT with number of bits in an integer"
++#endif
+ 
+ 
+ /*
++@@ LNUM_DOUBLE | LNUM_FLOAT | LNUM_LDOUBLE: Generic Lua number mode
++@@ LNUM_INT32 | LNUM_INT64: Integer type
++@@ LNUM_COMPLEX: Define for using 'a+bi' numbers
++@@
++@@ You can combine LNUM_xxx but only one of each group. I.e. '-DLNUM_FLOAT
++@@ -DLNUM_INT32 -DLNUM_COMPLEX' gives float range complex numbers, with 
++@@ 32-bit scalar integer range optimized.
++**
++** These are kept in a separate configuration file mainly for ease of patching
++** (can be changed if integerated to Lua proper).
++*/
++/*#define LNUM_DOUBLE*/
++/*#define LNUM_INT32*/
++#include "lnum_config.h"
++
++/*
+ @@ LUA_API is a mark for all core API functions.
+ @@ LUALIB_API is a mark for all standard library functions.
+ ** CHANGE them if you need to define those functions in some special way.
+@@ -383,22 +409,6 @@
+ 
+ 
+ /*
+-@@ LUAI_BITSINT defines the number of bits in an int.
+-** CHANGE here if Lua cannot automatically detect the number of bits of
+-** your machine. Probably you do not need to change this.
+-*/
+-/* avoid overflows in comparison */
+-#if INT_MAX-20 < 32760
+-#define LUAI_BITSINT	16
+-#elif INT_MAX > 2147483640L
+-/* int has at least 32 bits */
+-#define LUAI_BITSINT	32
+-#else
+-#error "you must define LUA_BITSINT with number of bits in an integer"
+-#endif
+-
+-
+-/*
+ @@ LUAI_UINT32 is an unsigned integer with at least 32 bits.
+ @@ LUAI_INT32 is an signed integer with at least 32 bits.
+ @@ LUAI_UMEM is an unsigned integer big enough to count the total
+@@ -425,6 +435,15 @@
+ #define LUAI_MEM	long
+ #endif
+ 
++/*
++@@ LUAI_BOOL carries 0 and nonzero (normally 1). It may be defined as 'char'
++** (to save memory), 'int' (for speed), 'bool' (for C++) or '_Bool' (C99)
++*/
++#ifdef __cplusplus
++# define LUAI_BOOL bool
++#else
++# define LUAI_BOOL int
++#endif
+ 
+ /*
+ @@ LUAI_MAXCALLS limits the number of nested calls.
+@@ -490,101 +509,6 @@
+ /* }================================================================== */
+ 
+ 
+-
+-
+-/*
+-** {==================================================================
+-@@ LUA_NUMBER is the type of numbers in Lua.
+-** CHANGE the following definitions only if you want to build Lua
+-** with a number type different from double. You may also need to
+-** change lua_number2int & lua_number2integer.
+-** ===================================================================
+-*/
+-
+-#define LUA_NUMBER_DOUBLE
+-#define LUA_NUMBER	double
+-
+-/*
+-@@ LUAI_UACNUMBER is the result of an 'usual argument conversion'
+-@* over a number.
+-*/
+-#define LUAI_UACNUMBER	double
+-
+-
+-/*
+-@@ LUA_NUMBER_SCAN is the format for reading numbers.
+-@@ LUA_NUMBER_FMT is the format for writing numbers.
+-@@ lua_number2str converts a number to a string.
+-@@ LUAI_MAXNUMBER2STR is maximum size of previous conversion.
+-@@ lua_str2number converts a string to a number.
+-*/
+-#define LUA_NUMBER_SCAN		"%lf"
+-#define LUA_NUMBER_FMT		"%.14g"
+-#define lua_number2str(s,n)	sprintf((s), LUA_NUMBER_FMT, (n))
+-#define LUAI_MAXNUMBER2STR	32 /* 16 digits, sign, point, and \0 */
+-#define lua_str2number(s,p)	strtod((s), (p))
+-
+-
+-/*
+-@@ The luai_num* macros define the primitive operations over numbers.
+-*/
+-#if defined(LUA_CORE)
+-#include <math.h>
+-#define luai_numadd(a,b)	((a)+(b))
+-#define luai_numsub(a,b)	((a)-(b))
+-#define luai_nummul(a,b)	((a)*(b))
+-#define luai_numdiv(a,b)	((a)/(b))
+-#define luai_nummod(a,b)	((a) - floor((a)/(b))*(b))
+-#define luai_numpow(a,b)	(pow(a,b))
+-#define luai_numunm(a)		(-(a))
+-#define luai_numeq(a,b)		((a)==(b))
+-#define luai_numlt(a,b)		((a)<(b))
+-#define luai_numle(a,b)		((a)<=(b))
+-#define luai_numisnan(a)	(!luai_numeq((a), (a)))
+-#endif
+-
+-
+-/*
+-@@ lua_number2int is a macro to convert lua_Number to int.
+-@@ lua_number2integer is a macro to convert lua_Number to lua_Integer.
+-** CHANGE them if you know a faster way to convert a lua_Number to
+-** int (with any rounding method and without throwing errors) in your
+-** system. In Pentium machines, a naive typecast from double to int
+-** in C is extremely slow, so any alternative is worth trying.
+-*/
+-
+-/* On a Pentium, resort to a trick */
+-#if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) && !defined(__SSE2__) && \
+-    (defined(__i386) || defined (_M_IX86) || defined(__i386__))
+-
+-/* On a Microsoft compiler, use assembler */
+-#if defined(_MSC_VER)
+-
+-#define lua_number2int(i,d)   __asm fld d   __asm fistp i
+-#define lua_number2integer(i,n)		lua_number2int(i, n)
+-
+-/* the next trick should work on any Pentium, but sometimes clashes
+-   with a DirectX idiosyncrasy */
+-#else
+-
+-union luai_Cast { double l_d; long l_l; };
+-#define lua_number2int(i,d) \
+-  { volatile union luai_Cast u; u.l_d = (d) + 6755399441055744.0; (i) = u.l_l; }
+-#define lua_number2integer(i,n)		lua_number2int(i, n)
+-
+-#endif
+-
+-
+-/* this option always works, but may be slow */
+-#else
+-#define lua_number2int(i,d)	((i)=(int)(d))
+-#define lua_number2integer(i,d)	((i)=(lua_Integer)(d))
+-
+-#endif
+-
+-/* }================================================================== */
+-
+-
+ /*
+ @@ LUAI_USER_ALIGNMENT_T is a type that requires maximum alignment.
+ ** CHANGE it if your system requires alignments larger than double. (For
+@@ -728,28 +652,6 @@ union luai_Cast { double l_d; long l_l;
+ #define luai_userstateyield(L,n)	((void)L)
+ 
+ 
+-/*
+-@@ LUA_INTFRMLEN is the length modifier for integer conversions
+-@* in 'string.format'.
+-@@ LUA_INTFRM_T is the integer type correspoding to the previous length
+-@* modifier.
+-** CHANGE them if your system supports long long or does not support long.
+-*/
+-
+-#if defined(LUA_USELONGLONG)
+-
+-#define LUA_INTFRMLEN		"ll"
+-#define LUA_INTFRM_T		long long
+-
+-#else
+-
+-#define LUA_INTFRMLEN		"l"
+-#define LUA_INTFRM_T		long
+-
+-#endif
+-
+-
+-
+ /* =================================================================== */
+ 
+ /*
+--- a/src/lundump.c
++++ b/src/lundump.c
+@@ -73,6 +73,13 @@ static lua_Number LoadNumber(LoadState*
+  return x;
+ }
+ 
++static lua_Integer LoadInteger(LoadState* S)
++{
++ lua_Integer x;
++ LoadVar(S,x);
++ return x;
++}
++
+ static TString* LoadString(LoadState* S)
+ {
+  size_t size;
+@@ -119,6 +126,9 @@ static void LoadConstants(LoadState* S,
+    case LUA_TNUMBER:
+ 	setnvalue(o,LoadNumber(S));
+ 	break;
++   case LUA_TINT:   /* Integer type saved in bytecode (see lcode.c) */
++	setivalue(o,LoadInteger(S));
++	break;
+    case LUA_TSTRING:
+ 	setsvalue2n(S->L,o,LoadString(S));
+ 	break;
+@@ -223,5 +233,22 @@ void luaU_header (char* h)
+  *h++=(char)sizeof(size_t);
+  *h++=(char)sizeof(Instruction);
+  *h++=(char)sizeof(lua_Number);
+- *h++=(char)(((lua_Number)0.5)==0);		/* is lua_Number integral? */
++
++ /* 
++  * Last byte of header (0/1 in unpatched Lua 5.1.3):
++  *
++  * 0: lua_Number is float or double, lua_Integer not used. (nonpatched only)
++  * 1: lua_Number is integer (nonpatched only)
++  *
++  * +2: LNUM_INT16: sizeof(lua_Integer)
++  * +4: LNUM_INT32: sizeof(lua_Integer)
++  * +8: LNUM_INT64: sizeof(lua_Integer)
++  *
++  * +0x80: LNUM_COMPLEX
++  */
++ *h++ = (char)(sizeof(lua_Integer)
++#ifdef LNUM_COMPLEX
++    | 0x80
++#endif
++    );
+ }
+--- a/src/lvm.c
++++ b/src/lvm.c
+@@ -25,22 +25,35 @@
+ #include "ltable.h"
+ #include "ltm.h"
+ #include "lvm.h"
+-
+-
++#include "llex.h"
++#include "lnum.h"
+ 
+ /* limit for table tag-method chains (to avoid loops) */
+ #define MAXTAGLOOP	100
+ 
+ 
+-const TValue *luaV_tonumber (const TValue *obj, TValue *n) {
+-  lua_Number num;
++/*
++ * If 'obj' is a string, it is tried to be interpreted as a number.
++ */
++const TValue *luaV_tonumber ( const TValue *obj, TValue *n) {
++  lua_Number d;
++  lua_Integer i;
++  
+   if (ttisnumber(obj)) return obj;
+-  if (ttisstring(obj) && luaO_str2d(svalue(obj), &num)) {
+-    setnvalue(n, num);
+-    return n;
+-  }
+-  else
+-    return NULL;
++
++  if (ttisstring(obj)) {
++    switch( luaO_str2d( svalue(obj), &d, &i ) ) {
++        case TK_INT:
++            setivalue(n,i); return n;
++        case TK_NUMBER: 
++            setnvalue(n,d); return n;
++#ifdef LNUM_COMPLEX
++        case TK_NUMBER2:    /* "N.NNNi", != 0 */
++            setnvalue_complex_fast(n, d*I); return n;
++#endif
++        }
++    }
++  return NULL;
+ }
+ 
+ 
+@@ -49,8 +62,7 @@ int luaV_tostring (lua_State *L, StkId o
+     return 0;
+   else {
+     char s[LUAI_MAXNUMBER2STR];
+-    lua_Number n = nvalue(obj);
+-    lua_number2str(s, n);
++    luaO_num2buf(s,obj);
+     setsvalue2s(L, obj, luaS_new(L, s));
+     return 1;
+   }
+@@ -222,59 +234,127 @@ static int l_strcmp (const TString *ls,
+ }
+ 
+ 
++#ifdef LNUM_COMPLEX
++void error_complex( lua_State *L, const TValue *l, const TValue *r )
++{
++  char buf1[ LUAI_MAXNUMBER2STR ];
++  char buf2[ LUAI_MAXNUMBER2STR ];
++  luaO_num2buf( buf1, l );
++  luaO_num2buf( buf2, r );
++  luaG_runerror( L, "unable to compare: %s with %s", buf1, buf2 );
++  /* no return */
++}
++#endif
++
++
+ int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) {
+   int res;
+-  if (ttype(l) != ttype(r))
++  int tl,tr;
++  lua_Integer tmp;
++
++  if (!ttype_ext_same(l,r))
+     return luaG_ordererror(L, l, r);
+-  else if (ttisnumber(l))
+-    return luai_numlt(nvalue(l), nvalue(r));
+-  else if (ttisstring(l))
+-    return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0;
+-  else if ((res = call_orderTM(L, l, r, TM_LT)) != -1)
++#ifdef LNUM_COMPLEX
++  if ( (nvalue_img(l)!=0) || (nvalue_img(r)!=0) )
++    error_complex( L, l, r );
++#endif
++  tl= ttype(l); tr= ttype(r);
++  if (tl==tr) {  /* clear arithmetics */
++    switch(tl) {
++      case LUA_TINT:      return ivalue(l) < ivalue(r);
++      case LUA_TNUMBER:   return luai_numlt(nvalue_fast(l), nvalue_fast(r));
++      case LUA_TSTRING:   return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0;
++    }
++  } else if (tl==LUA_TINT) {  /* l:int, r:num */
++    /* Avoid accuracy losing casts: if 'r' is integer by value, do comparisons
++     * in integer realm. Only otherwise cast 'l' to FP (which might change its
++     * value).
++     */
++    if (tt_integer_valued(r,&tmp)) 
++        return ivalue(l) < tmp;
++    else 
++        return luai_numlt( cast_num(ivalue(l)), nvalue_fast(r) );
++
++  } else if (tl==LUA_TNUMBER) {  /* l:num, r:int */
++    if (tt_integer_valued(l,&tmp)) 
++        return tmp < ivalue(r);
++    else
++        return luai_numlt( nvalue_fast(l), cast_num(ivalue(r)) );
++
++  } else if ((res = call_orderTM(L, l, r, TM_LT)) != -1)
+     return res;
++
+   return luaG_ordererror(L, l, r);
+ }
+ 
+ 
+ static int lessequal (lua_State *L, const TValue *l, const TValue *r) {
+   int res;
+-  if (ttype(l) != ttype(r))
++  int tl, tr;
++  lua_Integer tmp;
++
++  if (!ttype_ext_same(l,r))
+     return luaG_ordererror(L, l, r);
+-  else if (ttisnumber(l))
+-    return luai_numle(nvalue(l), nvalue(r));
+-  else if (ttisstring(l))
+-    return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0;
+-  else if ((res = call_orderTM(L, l, r, TM_LE)) != -1)  /* first try `le' */
++#ifdef LNUM_COMPLEX
++  if ( (nvalue_img(l)!=0) || (nvalue_img(r)!=0) )
++    error_complex( L, l, r );
++#endif
++  tl= ttype(l); tr= ttype(r);
++  if (tl==tr) {  /* clear arithmetics */
++    switch(tl) {
++      case LUA_TINT:      return ivalue(l) <= ivalue(r);
++      case LUA_TNUMBER:   return luai_numle(nvalue_fast(l), nvalue_fast(r));
++      case LUA_TSTRING:   return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0;
++    }
++  }
++  if (tl==LUA_TINT) {  /* l:int, r:num */
++    if (tt_integer_valued(r,&tmp)) 
++        return ivalue(l) <= tmp;
++    else
++        return luai_numle( cast_num(ivalue(l)), nvalue_fast(r) );
++
++  } else if (tl==LUA_TNUMBER) {  /* l:num, r:int */
++    if (tt_integer_valued(l,&tmp)) 
++        return tmp <= ivalue(r);
++    else
++        return luai_numle( nvalue_fast(l), cast_num(ivalue(r)) );
++
++  } else if ((res = call_orderTM(L, l, r, TM_LE)) != -1)  /* first try `le' */
+     return res;
+   else if ((res = call_orderTM(L, r, l, TM_LT)) != -1)  /* else try `lt' */
+     return !res;
++
+   return luaG_ordererror(L, l, r);
+ }
+ 
+ 
+-int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2) {
++/* Note: 'luaV_equalval()' and 'luaO_rawequalObj()' have largely overlapping
++ *       implementation. LUA_TNIL..LUA_TLIGHTUSERDATA cases could be handled
++ *       simply by the 'default' case here.
++ */
++int luaV_equalval (lua_State *L, const TValue *l, const TValue *r) {
+   const TValue *tm;
+-  lua_assert(ttype(t1) == ttype(t2));
+-  switch (ttype(t1)) {
++  lua_assert(ttype_ext_same(l,r));
++  switch (ttype(l)) {
+     case LUA_TNIL: return 1;
+-    case LUA_TNUMBER: return luai_numeq(nvalue(t1), nvalue(t2));
+-    case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2);  /* true must be 1 !! */
+-    case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2);
++    case LUA_TINT:
++    case LUA_TNUMBER: return luaO_rawequalObj(l,r);
++    case LUA_TBOOLEAN: return bvalue(l) == bvalue(r);  /* true must be 1 !! */
++    case LUA_TLIGHTUSERDATA: return pvalue(l) == pvalue(r);
+     case LUA_TUSERDATA: {
+-      if (uvalue(t1) == uvalue(t2)) return 1;
+-      tm = get_compTM(L, uvalue(t1)->metatable, uvalue(t2)->metatable,
+-                         TM_EQ);
++      if (uvalue(l) == uvalue(r)) return 1;
++      tm = get_compTM(L, uvalue(l)->metatable, uvalue(r)->metatable, TM_EQ);
+       break;  /* will try TM */
+     }
+     case LUA_TTABLE: {
+-      if (hvalue(t1) == hvalue(t2)) return 1;
+-      tm = get_compTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable, TM_EQ);
++      if (hvalue(l) == hvalue(r)) return 1;
++      tm = get_compTM(L, hvalue(l)->metatable, hvalue(r)->metatable, TM_EQ);
+       break;  /* will try TM */
+     }
+-    default: return gcvalue(t1) == gcvalue(t2);
++    default: return gcvalue(l) == gcvalue(r);
+   }
+   if (tm == NULL) return 0;  /* no TM? */
+-  callTMres(L, L->top, tm, t1, t2);  /* call TM */
++  callTMres(L, L->top, tm, l, r);  /* call TM */
+   return !l_isfalse(L->top);
+ }
+ 
+@@ -314,30 +394,6 @@ void luaV_concat (lua_State *L, int tota
+ }
+ 
+ 
+-static void Arith (lua_State *L, StkId ra, const TValue *rb,
+-                   const TValue *rc, TMS op) {
+-  TValue tempb, tempc;
+-  const TValue *b, *c;
+-  if ((b = luaV_tonumber(rb, &tempb)) != NULL &&
+-      (c = luaV_tonumber(rc, &tempc)) != NULL) {
+-    lua_Number nb = nvalue(b), nc = nvalue(c);
+-    switch (op) {
+-      case TM_ADD: setnvalue(ra, luai_numadd(nb, nc)); break;
+-      case TM_SUB: setnvalue(ra, luai_numsub(nb, nc)); break;
+-      case TM_MUL: setnvalue(ra, luai_nummul(nb, nc)); break;
+-      case TM_DIV: setnvalue(ra, luai_numdiv(nb, nc)); break;
+-      case TM_MOD: setnvalue(ra, luai_nummod(nb, nc)); break;
+-      case TM_POW: setnvalue(ra, luai_numpow(nb, nc)); break;
+-      case TM_UNM: setnvalue(ra, luai_numunm(nb)); break;
+-      default: lua_assert(0); break;
+-    }
+-  }
+-  else if (!call_binTM(L, rb, rc, ra, op))
+-    luaG_aritherror(L, rb, rc);
+-}
+-
+-
+-
+ /*
+ ** some macros for common tasks in `luaV_execute'
+ */
+@@ -361,17 +417,154 @@ static void Arith (lua_State *L, StkId r
+ #define Protect(x)	{ L->savedpc = pc; {x;}; base = L->base; }
+ 
+ 
+-#define arith_op(op,tm) { \
+-        TValue *rb = RKB(i); \
+-        TValue *rc = RKC(i); \
+-        if (ttisnumber(rb) && ttisnumber(rc)) { \
+-          lua_Number nb = nvalue(rb), nc = nvalue(rc); \
+-          setnvalue(ra, op(nb, nc)); \
+-        } \
+-        else \
+-          Protect(Arith(L, ra, rb, rc, tm)); \
++/* Note: if called for unary operations, 'rc'=='rb'.
++ */
++static void Arith (lua_State *L, StkId ra, const TValue *rb,
++                   const TValue *rc, TMS op) {
++  TValue tempb, tempc;
++  const TValue *b, *c;
++  lua_Number nb,nc;
++
++  if ((b = luaV_tonumber(rb, &tempb)) != NULL &&
++      (c = luaV_tonumber(rc, &tempc)) != NULL) {
++
++    /* Keep integer arithmetics in the integer realm, if possible.
++     */
++    if (ttisint(b) && ttisint(c)) {
++      lua_Integer ib = ivalue(b), ic = ivalue(c);
++      lua_Integer *ri = &ra->value.i;
++      ra->tt= LUA_TINT;  /* part of 'setivalue(ra)' */
++      switch (op) {
++        case TM_ADD: if (try_addint( ri, ib, ic)) return; break;
++        case TM_SUB: if (try_subint( ri, ib, ic)) return; break;
++        case TM_MUL: if (try_mulint( ri, ib, ic)) return; break;
++        case TM_DIV: if (try_divint( ri, ib, ic)) return; break;
++        case TM_MOD: if (try_modint( ri, ib, ic)) return; break;
++        case TM_POW: if (try_powint( ri, ib, ic)) return; break;
++        case TM_UNM: if (try_unmint( ri, ib)) return; break;
++        default: lua_assert(0);
+       }
++    }
++    /* Fallback to floating point, when leaving range. */
+ 
++#ifdef LNUM_COMPLEX
++    if ((nvalue_img(b)!=0) || (nvalue_img(c)!=0)) {
++      lua_Complex r;
++      if (op==TM_UNM) {
++        r= -nvalue_complex_fast(b);     /* never an integer (or scalar) */
++        setnvalue_complex_fast( ra, r );
++      } else {
++        lua_Complex bb= nvalue_complex(b), cc= nvalue_complex(c);
++        switch (op) {
++          case TM_ADD: r= bb + cc; break;
++          case TM_SUB: r= bb - cc; break;
++          case TM_MUL: r= bb * cc; break;
++          case TM_DIV: r= bb / cc; break;
++          case TM_MOD: 
++            luaG_runerror(L, "attempt to use %% on complex numbers");  /* no return */
++          case TM_POW: r= luai_vectpow( bb, cc ); break;
++          default: lua_assert(0); r=0;
++        }
++        setnvalue_complex( ra, r );
++      }
++      return;
++    }
++#endif
++    nb = nvalue(b); nc = nvalue(c);
++    switch (op) {
++      case TM_ADD: setnvalue(ra, luai_numadd(nb, nc)); return;
++      case TM_SUB: setnvalue(ra, luai_numsub(nb, nc)); return;
++      case TM_MUL: setnvalue(ra, luai_nummul(nb, nc)); return;
++      case TM_DIV: setnvalue(ra, luai_numdiv(nb, nc)); return;
++      case TM_MOD: setnvalue(ra, luai_nummod(nb, nc)); return;
++      case TM_POW: setnvalue(ra, luai_numpow(nb, nc)); return;
++      case TM_UNM: setnvalue(ra, luai_numunm(nb)); return;
++      default: lua_assert(0);
++    }
++  }
++  
++  /* Either operand not a number */
++  if (!call_binTM(L, rb, rc, ra, op))
++    luaG_aritherror(L, rb, rc);
++}
++
++/* Helper macro to sort arithmetic operations into four categories:
++ *  TK_INT: integer - integer operands
++ *  TK_NUMBER: number - number (non complex, either may be integer)
++ *  TK_NUMBER2: complex numbers (at least the other)
++ *  0: non-numeric (at least the other)
++*/
++#ifdef LNUM_COMPLEX
++static inline int arith_mode( const TValue *rb, const TValue *rc ) {
++  if (ttisint(rb) && ttisint(rc)) return TK_INT;
++  if (ttiscomplex(rb) || ttiscomplex(rc)) return TK_NUMBER2;
++  if (ttisnumber(rb) && ttisnumber(rc)) return TK_NUMBER;
++  return 0;
++}
++#else
++# define arith_mode(rb,rc) \
++    ( (ttisint(rb) && ttisint(rc)) ? TK_INT : \
++      (ttisnumber(rb) && ttisnumber(rc)) ? TK_NUMBER : 0 )
++#endif
++
++/* arith_op macro for two operators:
++ * automatically chooses, which function (number, integer, complex) to use
++ */
++#define ARITH_OP2_START( op_num, op_int ) \
++  int failed= 0; \
++  switch( arith_mode(rb,rc) ) { \
++    case TK_INT: \
++      if (op_int ( &(ra)->value.i, ivalue(rb), ivalue(rc) )) \
++        { ra->tt= LUA_TINT; break; } /* else flow through */ \
++    case TK_NUMBER: \
++      setnvalue(ra, op_num ( nvalue(rb), nvalue(rc) )); break;
++
++#define ARITH_OP2_END \
++    default: \
++      failed= 1; break; \
++  } if (!failed) continue;
++
++#define arith_op_continue_scalar( op_num, op_int ) \
++    ARITH_OP2_START( op_num, op_int ) \
++    ARITH_OP2_END
++
++#ifdef LNUM_COMPLEX
++# define arith_op_continue( op_num, op_int, op_complex ) \
++    ARITH_OP2_START( op_num, op_int ) \
++      case TK_NUMBER2: \
++        setnvalue_complex( ra, op_complex ( nvalue_complex(rb), nvalue_complex(rc) ) ); break; \
++    ARITH_OP2_END
++#else
++# define arith_op_continue(op_num,op_int,_) arith_op_continue_scalar(op_num,op_int)
++#endif
++
++/* arith_op macro for one operator:
++ */
++#define ARITH_OP1_START( op_num, op_int ) \
++  int failed= 0; \
++  switch( arith_mode(rb,rb) ) { \
++    case TK_INT: \
++      if (op_int ( &(ra)->value.i, ivalue(rb) )) \
++        { ra->tt= LUA_TINT; break; } /* else flow through */ \
++      case TK_NUMBER: \
++        setnvalue(ra, op_num (nvalue(rb))); break; \
++
++#define ARITH_OP1_END \
++      default: \
++        failed= 1; break; \
++  } if (!failed) continue;
++
++#ifdef LNUM_COMPLEX
++# define arith_op1_continue( op_num, op_int, op_complex ) \
++    ARITH_OP1_START( op_num, op_int ) \
++      case TK_NUMBER2: \
++        setnvalue_complex( ra, op_complex ( nvalue_complex_fast(rb) )); break; \
++    ARITH_OP1_END
++#else
++# define arith_op1_continue( op_num, op_int, _ ) \
++    ARITH_OP1_START( op_num, op_int ) \
++    ARITH_OP1_END
++#endif
+ 
+ 
+ void luaV_execute (lua_State *L, int nexeccalls) {
+@@ -472,38 +665,45 @@ void luaV_execute (lua_State *L, int nex
+         continue;
+       }
+       case OP_ADD: {
+-        arith_op(luai_numadd, TM_ADD);
++        TValue *rb = RKB(i), *rc= RKC(i);
++        arith_op_continue( luai_numadd, try_addint, luai_vectadd );
++        Protect(Arith(L, ra, rb, rc, TM_ADD)); \
+         continue;
+       }
+       case OP_SUB: {
+-        arith_op(luai_numsub, TM_SUB);
++        TValue *rb = RKB(i), *rc= RKC(i);
++        arith_op_continue( luai_numsub, try_subint, luai_vectsub );
++        Protect(Arith(L, ra, rb, rc, TM_SUB));
+         continue;
+       }
+       case OP_MUL: {
+-        arith_op(luai_nummul, TM_MUL);
++        TValue *rb = RKB(i), *rc= RKC(i);
++        arith_op_continue(luai_nummul, try_mulint, luai_vectmul);
++        Protect(Arith(L, ra, rb, rc, TM_MUL));
+         continue;
+       }
+       case OP_DIV: {
+-        arith_op(luai_numdiv, TM_DIV);
++        TValue *rb = RKB(i), *rc= RKC(i);
++        arith_op_continue(luai_numdiv, try_divint, luai_vectdiv);
++        Protect(Arith(L, ra, rb, rc, TM_DIV));
+         continue;
+       }
+       case OP_MOD: {
+-        arith_op(luai_nummod, TM_MOD);
++        TValue *rb = RKB(i), *rc= RKC(i);
++        arith_op_continue_scalar(luai_nummod, try_modint);  /* scalars only */
++        Protect(Arith(L, ra, rb, rc, TM_MOD));
+         continue;
+       }
+       case OP_POW: {
+-        arith_op(luai_numpow, TM_POW);
++        TValue *rb = RKB(i), *rc= RKC(i);
++        arith_op_continue(luai_numpow, try_powint, luai_vectpow);
++        Protect(Arith(L, ra, rb, rc, TM_POW));
+         continue;
+       }
+       case OP_UNM: {
+         TValue *rb = RB(i);
+-        if (ttisnumber(rb)) {
+-          lua_Number nb = nvalue(rb);
+-          setnvalue(ra, luai_numunm(nb));
+-        }
+-        else {
+-          Protect(Arith(L, ra, rb, rb, TM_UNM));
+-        }
++        arith_op1_continue(luai_numunm, try_unmint, luai_vectunm);
++        Protect(Arith(L, ra, rb, rb, TM_UNM));
+         continue;
+       }
+       case OP_NOT: {
+@@ -515,11 +715,11 @@ void luaV_execute (lua_State *L, int nex
+         const TValue *rb = RB(i);
+         switch (ttype(rb)) {
+           case LUA_TTABLE: {
+-            setnvalue(ra, cast_num(luaH_getn(hvalue(rb))));
++            setivalue(ra, luaH_getn(hvalue(rb)));
+             break;
+           }
+           case LUA_TSTRING: {
+-            setnvalue(ra, cast_num(tsvalue(rb)->len));
++            setivalue(ra, tsvalue(rb)->len);
+             break;
+           }
+           default: {  /* try metamethod */
+@@ -652,14 +852,30 @@ void luaV_execute (lua_State *L, int nex
+         }
+       }
+       case OP_FORLOOP: {
+-        lua_Number step = nvalue(ra+2);
+-        lua_Number idx = luai_numadd(nvalue(ra), step); /* increment index */
+-        lua_Number limit = nvalue(ra+1);
+-        if (luai_numlt(0, step) ? luai_numle(idx, limit)
+-                                : luai_numle(limit, idx)) {
+-          dojump(L, pc, GETARG_sBx(i));  /* jump back */
+-          setnvalue(ra, idx);  /* update internal index... */
+-          setnvalue(ra+3, idx);  /* ...and external index */
++        /* If start,step and limit are all integers, we don't need to check
++         * against overflow in the looping.
++         */
++        if (ttisint(ra) && ttisint(ra+1) && ttisint(ra+2)) {
++          lua_Integer step = ivalue(ra+2);
++          lua_Integer idx = ivalue(ra) + step; /* increment index */
++          lua_Integer limit = ivalue(ra+1);
++          if (step > 0 ? (idx <= limit) : (limit <= idx)) {
++            dojump(L, pc, GETARG_sBx(i));  /* jump back */
++            setivalue(ra, idx);  /* update internal index... */
++            setivalue(ra+3, idx);  /* ...and external index */
++          }
++        } else {
++          /* non-integer looping (don't use 'nvalue_fast', some may be integer!) 
++          */
++          lua_Number step = nvalue(ra+2);
++          lua_Number idx = luai_numadd(nvalue(ra), step); /* increment index */
++          lua_Number limit = nvalue(ra+1);
++          if (luai_numlt(0, step) ? luai_numle(idx, limit)
++                                  : luai_numle(limit, idx)) {
++            dojump(L, pc, GETARG_sBx(i));  /* jump back */
++            setnvalue(ra, idx);  /* update internal index... */
++            setnvalue(ra+3, idx);  /* ...and external index */
++          }
+         }
+         continue;
+       }
+@@ -668,13 +884,21 @@ void luaV_execute (lua_State *L, int nex
+         const TValue *plimit = ra+1;
+         const TValue *pstep = ra+2;
+         L->savedpc = pc;  /* next steps may throw errors */
++        /* Using same location for tonumber's both arguments, effectively does
++         * in-place modification (string->number). */
+         if (!tonumber(init, ra))
+           luaG_runerror(L, LUA_QL("for") " initial value must be a number");
+         else if (!tonumber(plimit, ra+1))
+           luaG_runerror(L, LUA_QL("for") " limit must be a number");
+         else if (!tonumber(pstep, ra+2))
+           luaG_runerror(L, LUA_QL("for") " step must be a number");
+-        setnvalue(ra, luai_numsub(nvalue(ra), nvalue(pstep)));
++        /* Step back one value (keep within integers if we can)
++         */
++        if (!( ttisint(ra) && ttisint(pstep) &&
++               try_subint( &ra->value.i, ivalue(ra), ivalue(pstep) ) )) {
++            /* don't use 'nvalue_fast()', values may be integer */
++            setnvalue(ra, luai_numsub(nvalue(ra), nvalue(pstep)));
++        }
+         dojump(L, pc, GETARG_sBx(i));
+         continue;
+       }
+@@ -711,7 +935,7 @@ void luaV_execute (lua_State *L, int nex
+           luaH_resizearray(L, h, last);  /* pre-alloc it at once */
+         for (; n > 0; n--) {
+           TValue *val = ra+n;
+-          setobj2t(L, luaH_setnum(L, h, last--), val);
++          setobj2t(L, luaH_setint(L, h, last--), val);
+           luaC_barriert(L, h, val);
+         }
+         continue;
+--- a/src/lvm.h
++++ b/src/lvm.h
+@@ -15,11 +15,9 @@
+ 
+ #define tostring(L,o) ((ttype(o) == LUA_TSTRING) || (luaV_tostring(L, o)))
+ 
+-#define tonumber(o,n)	(ttype(o) == LUA_TNUMBER || \
+-                         (((o) = luaV_tonumber(o,n)) != NULL))
++#define tonumber(o,n) (ttisnumber(o) || (((o) = luaV_tonumber(o,n)) != NULL))
+ 
+-#define equalobj(L,o1,o2) \
+-	(ttype(o1) == ttype(o2) && luaV_equalval(L, o1, o2))
++#define equalobj(L,o1,o2) (ttype_ext_same(o1,o2) && luaV_equalval(L, o1, o2))
+ 
+ 
+ LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r);
+--- a/src/print.c
++++ b/src/print.c
+@@ -14,6 +14,7 @@
+ #include "lobject.h"
+ #include "lopcodes.h"
+ #include "lundump.h"
++#include "lnum.h"
+ 
+ #define PrintFunction	luaU_print
+ 
+@@ -59,8 +60,16 @@ static void PrintConstant(const Proto* f
+   case LUA_TBOOLEAN:
+ 	printf(bvalue(o) ? "true" : "false");
+ 	break;
++  case LUA_TINT:
++	printf(LUA_INTEGER_FMT,ivalue(o));
++	break;
+   case LUA_TNUMBER:
+-	printf(LUA_NUMBER_FMT,nvalue(o));
++#ifdef LNUM_COMPLEX
++    // TBD: Do we get complex values here?
++    { lua_Number b= nvalue_img_fast(o);
++	  printf( LUA_NUMBER_FMT "%s" LUA_NUMBER_FMT "i", nvalue_fast(o), b>=0 ? "+":"", b ); }
++#endif
++	printf(LUA_NUMBER_FMT,nvalue_fast(o));
+ 	break;
+   case LUA_TSTRING:
+ 	PrintString(rawtsvalue(o));
diff --git a/package/utils/lua/patches/011-lnum-use-double.patch b/package/utils/lua/patches/011-lnum-use-double.patch
new file mode 100644
index 0000000..14c720b
--- /dev/null
+++ b/package/utils/lua/patches/011-lnum-use-double.patch
@@ -0,0 +1,11 @@
+--- a/src/lnum_config.h
++++ b/src/lnum_config.h
+@@ -11,7 +11,7 @@
+ ** Default number modes
+ */
+ #if (!defined LNUM_DOUBLE) && (!defined LNUM_FLOAT) && (!defined LNUM_LDOUBLE)
+-# define LNUM_FLOAT
++# define LNUM_DOUBLE
+ #endif
+ #if (!defined LNUM_INT16) && (!defined LNUM_INT32) && (!defined LNUM_INT64)
+ # define LNUM_INT32
diff --git a/package/utils/lua/patches/012-lnum-fix-ltle-relational-operators.patch b/package/utils/lua/patches/012-lnum-fix-ltle-relational-operators.patch
new file mode 100644
index 0000000..3d3d685
--- /dev/null
+++ b/package/utils/lua/patches/012-lnum-fix-ltle-relational-operators.patch
@@ -0,0 +1,22 @@
+--- a/src/lvm.c
++++ b/src/lvm.c
+@@ -281,7 +281,8 @@ int luaV_lessthan (lua_State *L, const T
+     else
+         return luai_numlt( nvalue_fast(l), cast_num(ivalue(r)) );
+ 
+-  } else if ((res = call_orderTM(L, l, r, TM_LT)) != -1)
++  } 
++  if ((res = call_orderTM(L, l, r, TM_LT)) != -1)
+     return res;
+ 
+   return luaG_ordererror(L, l, r);
+@@ -319,7 +320,8 @@ static int lessequal (lua_State *L, cons
+     else
+         return luai_numle( nvalue_fast(l), cast_num(ivalue(r)) );
+ 
+-  } else if ((res = call_orderTM(L, l, r, TM_LE)) != -1)  /* first try `le' */
++  } 
++  if ((res = call_orderTM(L, l, r, TM_LE)) != -1)  /* first try `le' */
+     return res;
+   else if ((res = call_orderTM(L, r, l, TM_LT)) != -1)  /* else try `lt' */
+     return !res;
diff --git a/package/utils/lua/patches/013-lnum-strtoul-parsing-fixes.patch b/package/utils/lua/patches/013-lnum-strtoul-parsing-fixes.patch
new file mode 100644
index 0000000..8887229
--- /dev/null
+++ b/package/utils/lua/patches/013-lnum-strtoul-parsing-fixes.patch
@@ -0,0 +1,41 @@
+--- a/src/lnum.c
++++ b/src/lnum.c
+@@ -127,6 +127,8 @@ static int luaO_str2i (const char *s, lu
+ #else
+       return 0;  /* Reject the number */
+ #endif
++    } else if (v > LUA_INTEGER_MAX) {
++      return TK_NUMBER;
+     }
+   } else if ((v > LUA_INTEGER_MAX) || (*endptr && (!isspace(*endptr)))) {
+     return TK_NUMBER;	/* not in signed range, or has '.', 'e' etc. trailing */
+@@ -310,3 +312,13 @@ int try_unmint( lua_Integer *r, lua_Inte
+   return 0;
+ }
+ 
++#ifdef LONG_OVERFLOW_LUA_INTEGER
++unsigned LUA_INTEGER lua_str2ul( const char *str, char **endptr, int base ) {
++  unsigned long v= strtoul(str, endptr, base);
++  if ( v > LUA_INTEGER_MAX ) {
++    errno= ERANGE;
++    v= ULONG_MAX;
++  }
++  return (unsigned LUA_INTEGER)v;
++}
++#endif
+--- a/src/lnum_config.h
++++ b/src/lnum_config.h
+@@ -141,7 +141,12 @@
+ #endif
+ 
+ #ifndef lua_str2ul
+-# define lua_str2ul (unsigned LUA_INTEGER)strtoul
++# if LONG_MAX > LUA_INTEGER_MAX
++#   define LONG_OVERFLOW_LUA_INTEGER
++    unsigned LUA_INTEGER lua_str2ul( const char *str, char **endptr, int base );
++# else
++#  define lua_str2ul (unsigned LUA_INTEGER)strtoul
++# endif
+ #endif
+ #ifndef LUA_INTEGER_MIN
+ # define LUA_INTEGER_MIN (-LUA_INTEGER_MAX -1)  /* -2^16|32 */
diff --git a/package/utils/lua/patches/015-lnum-ppc-compat.patch b/package/utils/lua/patches/015-lnum-ppc-compat.patch
new file mode 100644
index 0000000..2ea59f1
--- /dev/null
+++ b/package/utils/lua/patches/015-lnum-ppc-compat.patch
@@ -0,0 +1,11 @@
+--- a/src/lua.h
++++ b/src/lua.h
+@@ -79,7 +79,7 @@ typedef void * (*lua_Alloc) (void *ud, v
+  *     not acceptable for 5.1, maybe 5.2 onwards?
+  *  9: greater than existing (5.1) type values.
+ */
+-#define LUA_TINT (-2)
++#define LUA_TINT 9
+ 
+ #define LUA_TNIL		0
+ #define LUA_TBOOLEAN		1
diff --git a/package/utils/lua/patches/020-shared_liblua.patch b/package/utils/lua/patches/020-shared_liblua.patch
new file mode 100644
index 0000000..f67ee2b
--- /dev/null
+++ b/package/utils/lua/patches/020-shared_liblua.patch
@@ -0,0 +1,140 @@
+--- a/Makefile
++++ b/Makefile
+@@ -42,8 +42,8 @@ PLATS= aix ansi bsd freebsd generic linu
+ 
+ # What to install.
+ TO_BIN= lua$V luac$V
+-TO_INC= lua.h luaconf.h lualib.h lauxlib.h ../etc/lua.hpp
+-TO_LIB= liblua.a
++TO_INC= lua.h luaconf.h lualib.h lauxlib.h ../etc/lua.hpp lnum_config.h
++TO_LIB= liblua.a liblua.so.$R
+ TO_MAN= lua$V.1 luac$V.1
+ 
+ # Lua version and release.
+@@ -63,6 +63,7 @@ install: dummy
+ 	cd src && $(INSTALL_EXEC) $(TO_BIN) $(INSTALL_BIN)
+ 	cd src && $(INSTALL_DATA) $(TO_INC) $(INSTALL_INC)
+ 	cd src && $(INSTALL_DATA) $(TO_LIB) $(INSTALL_LIB)
++	ln -s liblua.so.$R $(INSTALL_LIB)/liblua.so
+ 	cd doc && $(INSTALL_DATA) $(TO_MAN) $(INSTALL_MAN)
+ 
+ ranlib:
+--- a/src/ldo.h
++++ b/src/ldo.h
+@@ -46,7 +46,7 @@ LUAI_FUNC int luaD_pcall (lua_State *L,
+ LUAI_FUNC int luaD_poscall (lua_State *L, StkId firstResult);
+ LUAI_FUNC void luaD_reallocCI (lua_State *L, int newsize);
+ LUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize);
+-LUAI_FUNC void luaD_growstack (lua_State *L, int n);
++LUA_API void luaD_growstack (lua_State *L, int n);
+ 
+ LUAI_FUNC void luaD_throw (lua_State *L, int errcode);
+ LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud);
+--- a/src/lfunc.h
++++ b/src/lfunc.h
+@@ -18,7 +18,7 @@
+                          cast(int, sizeof(TValue *)*((n)-1)))
+ 
+ 
+-LUAI_FUNC Proto *luaF_newproto (lua_State *L);
++LUA_API Proto *luaF_newproto (lua_State *L);
+ LUAI_FUNC Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e);
+ LUAI_FUNC Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e);
+ LUAI_FUNC UpVal *luaF_newupval (lua_State *L);
+--- a/src/lmem.h
++++ b/src/lmem.h
+@@ -38,9 +38,9 @@
+    ((v)=cast(t *, luaM_reallocv(L, v, oldn, n, sizeof(t))))
+ 
+ 
+-LUAI_FUNC void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize,
++LUA_API void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize,
+                                                           size_t size);
+-LUAI_FUNC void *luaM_toobig (lua_State *L);
++LUA_API void *luaM_toobig (lua_State *L);
+ LUAI_FUNC void *luaM_growaux_ (lua_State *L, void *block, int *size,
+                                size_t size_elem, int limit,
+                                const char *errormsg);
+--- a/src/lstring.h
++++ b/src/lstring.h
+@@ -25,7 +25,7 @@
+ 
+ LUAI_FUNC void luaS_resize (lua_State *L, int newsize);
+ LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, Table *e);
+-LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l);
++LUA_API TString *luaS_newlstr (lua_State *L, const char *str, size_t l);
+ 
+ 
+ #endif
+--- a/src/lundump.h
++++ b/src/lundump.h
+@@ -17,7 +17,7 @@ LUAI_FUNC Proto* luaU_undump (lua_State*
+ LUAI_FUNC void luaU_header (char* h);
+ 
+ /* dump one chunk; from ldump.c */
+-LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip);
++LUA_API int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip);
+ 
+ #ifdef luac_c
+ /* print one chunk; from print.c */
+--- a/src/Makefile
++++ b/src/Makefile
+@@ -23,6 +23,7 @@ MYLIBS=
+ PLATS= aix ansi bsd freebsd generic linux macosx mingw posix solaris
+ 
+ LUA_A=	liblua.a
++LUA_SO= liblua.so
+ CORE_O=	lapi.o lcode.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o lmem.o \
+ 	lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o ltm.o  \
+ 	lundump.o lvm.o lzio.o lnum.o
+@@ -33,11 +34,12 @@ LUA_T=	lua$V
+ LUA_O=	lua.o
+ 
+ LUAC_T=	luac$V
+-LUAC_O=	luac.o print.o
++LUAC_O=	luac.o print.o lopcodes.o
+ 
+ ALL_O= $(CORE_O) $(LIB_O) $(LUA_O) $(LUAC_O)
+-ALL_T= $(LUA_A) $(LUA_T) $(LUAC_T)
++ALL_T= $(LUA_A) $(LUA_SO) $(LUA_T) $(LUAC_T)
+ ALL_A= $(LUA_A)
++ALL_SO= $(LUA_SO)
+ 
+ default: $(PLAT)
+ 
+@@ -47,14 +49,23 @@ o:	$(ALL_O)
+ 
+ a:	$(ALL_A)
+ 
++so:	$(ALL_SO)
++
+ $(LUA_A): $(CORE_O) $(LIB_O)
+ 	$(AR) $@ $(CORE_O) $(LIB_O)	# DLL needs all object files
+ 	$(RANLIB) $@
+ 
+-$(LUA_T): $(LUA_O) $(LUA_A)
+-	$(CC) -o $@ $(MYLDFLAGS) $(LUA_O) $(LUA_A) $(LIBS)
++$(LUA_SO): $(CORE_O) $(LIB_O)
++	$(CC) -o $@.$(PKG_VERSION) -shared -Wl,-soname="$@.$(PKG_VERSION)" $?
++	ln -fs $@.$(PKG_VERSION) $@
++
++$(LUA_T): $(LUA_O) $(LUA_SO)
++	$(CC) -o $@ -L. -llua $(MYLDFLAGS) $(LUA_O) $(LIBS)
++
++$(LUAC_T): $(LUAC_O) $(LUA_SO)
++	$(CC) -o $@ -L. -llua $(MYLDFLAGS) $(LUAC_O) $(LIBS)
+ 
+-$(LUAC_T): $(LUAC_O) $(LUA_A)
++$(LUAC_T)-host: $(LUAC_O) $(LUA_A)
+ 	$(CC) -o $@ $(MYLDFLAGS) $(LUAC_O) $(LUA_A) $(LIBS)
+ 
+ clean:
+@@ -96,7 +107,7 @@ generic:
+ 	$(MAKE) all MYCFLAGS=
+ 
+ linux:
+-	$(MAKE) all MYCFLAGS=-DLUA_USE_LINUX MYLIBS="-Wl,-E -ldl -lreadline -lhistory -lncurses"
++	$(MAKE) all MYCFLAGS+=-DLUA_USE_LINUX MYLIBS="-Wl,-E -ldl -lreadline -lhistory -lncurses"
+ 
+ macosx:
+ 	$(MAKE) all MYCFLAGS=-DLUA_USE_LINUX MYLIBS="-lreadline"
diff --git a/package/utils/lua/patches/030-archindependent-bytecode.patch b/package/utils/lua/patches/030-archindependent-bytecode.patch
new file mode 100644
index 0000000..8dfef85
--- /dev/null
+++ b/package/utils/lua/patches/030-archindependent-bytecode.patch
@@ -0,0 +1,111 @@
+--- a/src/ldump.c
++++ b/src/ldump.c
+@@ -67,12 +67,12 @@ static void DumpString(const TString* s,
+ {
+  if (s==NULL || getstr(s)==NULL)
+  {
+-  size_t size=0;
++  unsigned int size=0;
+   DumpVar(size,D);
+  }
+  else
+  {
+-  size_t size=s->tsv.len+1;		/* include trailing '\0' */
++  unsigned int size=s->tsv.len+1;		/* include trailing '\0' */
+   DumpVar(size,D);
+   DumpBlock(getstr(s),size,D);
+  }
+--- a/src/lundump.c
++++ b/src/lundump.c
+@@ -25,6 +25,7 @@ typedef struct {
+  ZIO* Z;
+  Mbuffer* b;
+  const char* name;
++ int swap;
+ } LoadState;
+ 
+ #ifdef LUAC_TRUST_BINARIES
+@@ -40,7 +41,6 @@ static void error(LoadState* S, const ch
+ }
+ #endif
+ 
+-#define LoadMem(S,b,n,size)	LoadBlock(S,b,(n)*(size))
+ #define	LoadByte(S)		(lu_byte)LoadChar(S)
+ #define LoadVar(S,x)		LoadMem(S,&x,1,sizeof(x))
+ #define LoadVector(S,b,n,size)	LoadMem(S,b,n,size)
+@@ -51,6 +51,49 @@ static void LoadBlock(LoadState* S, void
+  IF (r!=0, "unexpected end");
+ }
+ 
++static void LoadMem (LoadState* S, void* b, int n, size_t size)
++{
++ LoadBlock(S,b,n*size);
++ if (S->swap)
++ {
++  char* p=(char*) b;
++  char c;
++  switch (size)
++  {
++   case 1:
++  	break;
++   case 2:
++	while (n--)
++	{
++	 c=p[0]; p[0]=p[1]; p[1]=c;
++	 p+=2;
++	}
++  	break;
++   case 4:
++	while (n--)
++	{
++	 c=p[0]; p[0]=p[3]; p[3]=c;
++	 c=p[1]; p[1]=p[2]; p[2]=c;
++	 p+=4;
++	}
++  	break;
++   case 8:
++	while (n--)
++	{
++	 c=p[0]; p[0]=p[7]; p[7]=c;
++	 c=p[1]; p[1]=p[6]; p[6]=c;
++	 c=p[2]; p[2]=p[5]; p[5]=c;
++	 c=p[3]; p[3]=p[4]; p[4]=c;
++	 p+=8;
++	}
++  	break;
++   default:
++   	IF(1, "bad size");
++  	break;
++  }
++ }
++}
++
+ static int LoadChar(LoadState* S)
+ {
+  char x;
+@@ -82,7 +125,7 @@ static lua_Integer LoadInteger(LoadState
+ 
+ static TString* LoadString(LoadState* S)
+ {
+- size_t size;
++ unsigned int size;
+  LoadVar(S,size);
+  if (size==0)
+   return NULL;
+@@ -196,6 +239,7 @@ static void LoadHeader(LoadState* S)
+  char s[LUAC_HEADERSIZE];
+  luaU_header(h);
+  LoadBlock(S,s,LUAC_HEADERSIZE);
++ S->swap=(s[6]!=h[6]); s[6]=h[6];
+  IF (memcmp(h,s,LUAC_HEADERSIZE)!=0, "bad header");
+ }
+ 
+@@ -230,7 +274,7 @@ void luaU_header (char* h)
+  *h++=(char)LUAC_FORMAT;
+  *h++=(char)*(char*)&x;				/* endianness */
+  *h++=(char)sizeof(int);
+- *h++=(char)sizeof(size_t);
++ *h++=(char)sizeof(unsigned int);
+  *h++=(char)sizeof(Instruction);
+  *h++=(char)sizeof(lua_Number);
+ 
diff --git a/package/utils/lua/patches/040-use-symbolic-functions.patch b/package/utils/lua/patches/040-use-symbolic-functions.patch
new file mode 100644
index 0000000..f590695
--- /dev/null
+++ b/package/utils/lua/patches/040-use-symbolic-functions.patch
@@ -0,0 +1,11 @@
+--- a/src/Makefile
++++ b/src/Makefile
+@@ -56,7 +56,7 @@ $(LUA_A): $(CORE_O) $(LIB_O)
+ 	$(RANLIB) $@
+ 
+ $(LUA_SO): $(CORE_O) $(LIB_O)
+-	$(CC) -o $@.$(PKG_VERSION) -shared -Wl,-soname="$@.$(PKG_VERSION)" $?
++	$(CC) -o $@.$(PKG_VERSION) -Wl,-Bsymbolic-functions -shared -Wl,-soname="$@.$(PKG_VERSION)" $?
+ 	ln -fs $@.$(PKG_VERSION) $@
+ 
+ $(LUA_T): $(LUA_O) $(LUA_SO)
diff --git a/package/utils/lua/patches/050-honor-cflags.patch b/package/utils/lua/patches/050-honor-cflags.patch
new file mode 100644
index 0000000..d221c4e
--- /dev/null
+++ b/package/utils/lua/patches/050-honor-cflags.patch
@@ -0,0 +1,11 @@
+--- a/src/Makefile
++++ b/src/Makefile
+@@ -56,7 +56,7 @@ $(LUA_A): $(CORE_O) $(LIB_O)
+ 	$(RANLIB) $@
+ 
+ $(LUA_SO): $(CORE_O) $(LIB_O)
+-	$(CC) -o $@.$(PKG_VERSION) -Wl,-Bsymbolic-functions -shared -Wl,-soname="$@.$(PKG_VERSION)" $?
++	$(CC) -o $@.$(PKG_VERSION) -Wl,-Bsymbolic-functions $(MYLDFLAGS) -shared -Wl,-soname="$@.$(PKG_VERSION)" $?
+ 	ln -fs $@.$(PKG_VERSION) $@
+ 
+ $(LUA_T): $(LUA_O) $(LUA_SO)
diff --git a/package/utils/lua/patches/100-no_readline.patch b/package/utils/lua/patches/100-no_readline.patch
new file mode 100644
index 0000000..0350e47
--- /dev/null
+++ b/package/utils/lua/patches/100-no_readline.patch
@@ -0,0 +1,49 @@
+--- a/src/luaconf.h
++++ b/src/luaconf.h
+@@ -38,7 +38,6 @@
+ #if defined(LUA_USE_LINUX)
+ #define LUA_USE_POSIX
+ #define LUA_USE_DLOPEN		/* needs an extra library: -ldl */
+-#define LUA_USE_READLINE	/* needs some extra libraries */
+ #endif
+ 
+ #if defined(LUA_USE_MACOSX)
+--- a/src/Makefile
++++ b/src/Makefile
+@@ -17,6 +17,7 @@ LIBS= -lm $(MYLIBS)
+ MYCFLAGS=
+ MYLDFLAGS=
+ MYLIBS=
++# USE_READLINE=1
+ 
+ # == END OF USER SETTINGS. NO NEED TO CHANGE ANYTHING BELOW THIS LINE =========
+ 
+@@ -86,7 +87,7 @@ echo:
+ 	@echo "MYLIBS = $(MYLIBS)"
+ 
+ # convenience targets for popular platforms
+-
++RFLAG=$(if $(USE_READLINE),-DLUA_USE_READLINE)
+ none:
+ 	@echo "Please choose a platform:"
+ 	@echo "   $(PLATS)"
+@@ -101,16 +102,16 @@ bsd:
+ 	$(MAKE) all MYCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN" MYLIBS="-Wl,-E"
+ 
+ freebsd:
+-	$(MAKE) all MYCFLAGS="-DLUA_USE_LINUX" MYLIBS="-Wl,-E -lreadline"
++	$(MAKE) all MYCFLAGS="-DLUA_USE_LINUX $(RFLAG)" MYLIBS="-Wl,-E$(if $(USE_READLINE), -lreadline)"
+ 
+ generic:
+ 	$(MAKE) all MYCFLAGS=
+ 
+ linux:
+-	$(MAKE) all MYCFLAGS+=-DLUA_USE_LINUX MYLIBS="-Wl,-E -ldl -lreadline -lhistory -lncurses"
++	$(MAKE) all MYCFLAGS+="-DLUA_USE_LINUX $(RFLAG)" MYLIBS="-Wl,-E -ldl $(if $(USE_READLINE), -lreadline -lhistory -lncurses)"
+ 
+ macosx:
+-	$(MAKE) all MYCFLAGS=-DLUA_USE_LINUX MYLIBS="-lreadline"
++	$(MAKE) all MYCFLAGS=-DLUA_USE_LINUX $(if $(USE_READLINE), MYLIBS="-lreadline")
+ # use this on Mac OS X 10.3-
+ #	$(MAKE) all MYCFLAGS=-DLUA_USE_MACOSX
+ 
diff --git a/package/utils/lua/patches/200-lua-path.patch b/package/utils/lua/patches/200-lua-path.patch
new file mode 100644
index 0000000..0544577
--- /dev/null
+++ b/package/utils/lua/patches/200-lua-path.patch
@@ -0,0 +1,15 @@
+--- a/src/luaconf.h
++++ b/src/luaconf.h
+@@ -95,9 +95,9 @@
+ 	".\\?.dll;"  LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll"
+ 
+ #else
+-#define LUA_ROOT	"/usr/local/"
+-#define LUA_LDIR	LUA_ROOT "share/lua/5.1/"
+-#define LUA_CDIR	LUA_ROOT "lib/lua/5.1/"
++#define LUA_ROOT	"/usr/"
++#define LUA_LDIR	LUA_ROOT "share/lua/"
++#define LUA_CDIR	LUA_ROOT "lib/lua/"
+ #define LUA_PATH_DEFAULT  \
+ 		"./?.lua;"  LUA_LDIR"?.lua;"  LUA_LDIR"?/init.lua;" \
+ 		            LUA_CDIR"?.lua;"  LUA_CDIR"?/init.lua"
diff --git a/package/utils/lua/patches/300-opcode_performance.patch b/package/utils/lua/patches/300-opcode_performance.patch
new file mode 100644
index 0000000..b971e09
--- /dev/null
+++ b/package/utils/lua/patches/300-opcode_performance.patch
@@ -0,0 +1,363 @@
+--- a/src/lvm.c
++++ b/src/lvm.c
+@@ -31,6 +31,9 @@
+ /* limit for table tag-method chains (to avoid loops) */
+ #define MAXTAGLOOP	100
+ 
++#ifdef __GNUC__
++#define COMPUTED_GOTO 1
++#endif
+ 
+ /*
+  * If 'obj' is a string, it is tried to be interpreted as a number.
+@@ -568,12 +571,63 @@ static inline int arith_mode( const TVal
+     ARITH_OP1_END
+ #endif
+ 
++#ifdef COMPUTED_GOTO
++#define OPCODE_TARGET(op) DO_OP_##op:
++#define CALL_OPCODE(op) goto *opcodes[op];
++#define OPCODE_PTR(op) [OP_##op] = &&DO_OP_##op
++#else
++#define OPCODE_TARGET(op) case OP_##op:
++#define CALL_OPCODE(op) switch (op)
++#endif
++
+ 
+ void luaV_execute (lua_State *L, int nexeccalls) {
+   LClosure *cl;
+   StkId base;
+   TValue *k;
+   const Instruction *pc;
++#ifdef COMPUTED_GOTO
++  static const void *opcodes[] = {
++   OPCODE_PTR(MOVE),
++   OPCODE_PTR(LOADK),
++   OPCODE_PTR(LOADBOOL),
++   OPCODE_PTR(LOADNIL),
++   OPCODE_PTR(GETUPVAL),
++   OPCODE_PTR(GETGLOBAL),
++   OPCODE_PTR(GETTABLE),
++   OPCODE_PTR(SETGLOBAL),
++   OPCODE_PTR(SETUPVAL),
++   OPCODE_PTR(SETTABLE),
++   OPCODE_PTR(NEWTABLE),
++   OPCODE_PTR(SELF),
++   OPCODE_PTR(ADD),
++   OPCODE_PTR(SUB),
++   OPCODE_PTR(MUL),
++   OPCODE_PTR(DIV),
++   OPCODE_PTR(MOD),
++   OPCODE_PTR(POW),
++   OPCODE_PTR(UNM),
++   OPCODE_PTR(NOT),
++   OPCODE_PTR(LEN),
++   OPCODE_PTR(CONCAT),
++   OPCODE_PTR(JMP),
++   OPCODE_PTR(EQ),
++   OPCODE_PTR(LT),
++   OPCODE_PTR(LE),
++   OPCODE_PTR(TEST),
++   OPCODE_PTR(TESTSET),
++   OPCODE_PTR(CALL),
++   OPCODE_PTR(TAILCALL),
++   OPCODE_PTR(RETURN),
++   OPCODE_PTR(FORLOOP),
++   OPCODE_PTR(FORPREP),
++   OPCODE_PTR(TFORLOOP),
++   OPCODE_PTR(SETLIST),
++   OPCODE_PTR(CLOSE),
++   OPCODE_PTR(CLOSURE),
++   OPCODE_PTR(VARARG)
++  };
++#endif
+  reentry:  /* entry point */
+   lua_assert(isLua(L->ci));
+   pc = L->savedpc;
+@@ -598,33 +652,33 @@ void luaV_execute (lua_State *L, int nex
+     lua_assert(base == L->base && L->base == L->ci->base);
+     lua_assert(base <= L->top && L->top <= L->stack + L->stacksize);
+     lua_assert(L->top == L->ci->top || luaG_checkopenop(i));
+-    switch (GET_OPCODE(i)) {
+-      case OP_MOVE: {
++    CALL_OPCODE(GET_OPCODE(i)) {
++      OPCODE_TARGET(MOVE) {
+         setobjs2s(L, ra, RB(i));
+         continue;
+       }
+-      case OP_LOADK: {
++      OPCODE_TARGET(LOADK) {
+         setobj2s(L, ra, KBx(i));
+         continue;
+       }
+-      case OP_LOADBOOL: {
++      OPCODE_TARGET(LOADBOOL) {
+         setbvalue(ra, GETARG_B(i));
+         if (GETARG_C(i)) pc++;  /* skip next instruction (if C) */
+         continue;
+       }
+-      case OP_LOADNIL: {
++      OPCODE_TARGET(LOADNIL) {
+         TValue *rb = RB(i);
+         do {
+           setnilvalue(rb--);
+         } while (rb >= ra);
+         continue;
+       }
+-      case OP_GETUPVAL: {
++      OPCODE_TARGET(GETUPVAL) {
+         int b = GETARG_B(i);
+         setobj2s(L, ra, cl->upvals[b]->v);
+         continue;
+       }
+-      case OP_GETGLOBAL: {
++      OPCODE_TARGET(GETGLOBAL) {
+         TValue g;
+         TValue *rb = KBx(i);
+         sethvalue(L, &g, cl->env);
+@@ -632,88 +686,88 @@ void luaV_execute (lua_State *L, int nex
+         Protect(luaV_gettable(L, &g, rb, ra));
+         continue;
+       }
+-      case OP_GETTABLE: {
++      OPCODE_TARGET(GETTABLE) {
+         Protect(luaV_gettable(L, RB(i), RKC(i), ra));
+         continue;
+       }
+-      case OP_SETGLOBAL: {
++      OPCODE_TARGET(SETGLOBAL) {
+         TValue g;
+         sethvalue(L, &g, cl->env);
+         lua_assert(ttisstring(KBx(i)));
+         Protect(luaV_settable(L, &g, KBx(i), ra));
+         continue;
+       }
+-      case OP_SETUPVAL: {
++      OPCODE_TARGET(SETUPVAL) {
+         UpVal *uv = cl->upvals[GETARG_B(i)];
+         setobj(L, uv->v, ra);
+         luaC_barrier(L, uv, ra);
+         continue;
+       }
+-      case OP_SETTABLE: {
++      OPCODE_TARGET(SETTABLE) {
+         Protect(luaV_settable(L, ra, RKB(i), RKC(i)));
+         continue;
+       }
+-      case OP_NEWTABLE: {
++      OPCODE_TARGET(NEWTABLE) {
+         int b = GETARG_B(i);
+         int c = GETARG_C(i);
+         sethvalue(L, ra, luaH_new(L, luaO_fb2int(b), luaO_fb2int(c)));
+         Protect(luaC_checkGC(L));
+         continue;
+       }
+-      case OP_SELF: {
++      OPCODE_TARGET(SELF) {
+         StkId rb = RB(i);
+         setobjs2s(L, ra+1, rb);
+         Protect(luaV_gettable(L, rb, RKC(i), ra));
+         continue;
+       }
+-      case OP_ADD: {
++      OPCODE_TARGET(ADD) {
+         TValue *rb = RKB(i), *rc= RKC(i);
+         arith_op_continue( luai_numadd, try_addint, luai_vectadd );
+         Protect(Arith(L, ra, rb, rc, TM_ADD)); \
+         continue;
+       }
+-      case OP_SUB: {
++      OPCODE_TARGET(SUB) {
+         TValue *rb = RKB(i), *rc= RKC(i);
+         arith_op_continue( luai_numsub, try_subint, luai_vectsub );
+         Protect(Arith(L, ra, rb, rc, TM_SUB));
+         continue;
+       }
+-      case OP_MUL: {
++      OPCODE_TARGET(MUL) {
+         TValue *rb = RKB(i), *rc= RKC(i);
+         arith_op_continue(luai_nummul, try_mulint, luai_vectmul);
+         Protect(Arith(L, ra, rb, rc, TM_MUL));
+         continue;
+       }
+-      case OP_DIV: {
++      OPCODE_TARGET(DIV) {
+         TValue *rb = RKB(i), *rc= RKC(i);
+         arith_op_continue(luai_numdiv, try_divint, luai_vectdiv);
+         Protect(Arith(L, ra, rb, rc, TM_DIV));
+         continue;
+       }
+-      case OP_MOD: {
++      OPCODE_TARGET(MOD) {
+         TValue *rb = RKB(i), *rc= RKC(i);
+         arith_op_continue_scalar(luai_nummod, try_modint);  /* scalars only */
+         Protect(Arith(L, ra, rb, rc, TM_MOD));
+         continue;
+       }
+-      case OP_POW: {
++      OPCODE_TARGET(POW) {
+         TValue *rb = RKB(i), *rc= RKC(i);
+         arith_op_continue(luai_numpow, try_powint, luai_vectpow);
+         Protect(Arith(L, ra, rb, rc, TM_POW));
+         continue;
+       }
+-      case OP_UNM: {
++      OPCODE_TARGET(UNM) {
+         TValue *rb = RB(i);
+         arith_op1_continue(luai_numunm, try_unmint, luai_vectunm);
+         Protect(Arith(L, ra, rb, rb, TM_UNM));
+         continue;
+       }
+-      case OP_NOT: {
++      OPCODE_TARGET(NOT) {
+         int res = l_isfalse(RB(i));  /* next assignment may change this value */
+         setbvalue(ra, res);
+         continue;
+       }
+-      case OP_LEN: {
++      OPCODE_TARGET(LEN) {
+         const TValue *rb = RB(i);
+         switch (ttype(rb)) {
+           case LUA_TTABLE: {
+@@ -733,18 +787,18 @@ void luaV_execute (lua_State *L, int nex
+         }
+         continue;
+       }
+-      case OP_CONCAT: {
++      OPCODE_TARGET(CONCAT) {
+         int b = GETARG_B(i);
+         int c = GETARG_C(i);
+         Protect(luaV_concat(L, c-b+1, c); luaC_checkGC(L));
+         setobjs2s(L, RA(i), base+b);
+         continue;
+       }
+-      case OP_JMP: {
++      OPCODE_TARGET(JMP) {
+         dojump(L, pc, GETARG_sBx(i));
+         continue;
+       }
+-      case OP_EQ: {
++      OPCODE_TARGET(EQ) {
+         TValue *rb = RKB(i);
+         TValue *rc = RKC(i);
+         Protect(
+@@ -754,7 +808,7 @@ void luaV_execute (lua_State *L, int nex
+         pc++;
+         continue;
+       }
+-      case OP_LT: {
++      OPCODE_TARGET(LT) {
+         Protect(
+           if (luaV_lessthan(L, RKB(i), RKC(i)) == GETARG_A(i))
+             dojump(L, pc, GETARG_sBx(*pc));
+@@ -762,7 +816,7 @@ void luaV_execute (lua_State *L, int nex
+         pc++;
+         continue;
+       }
+-      case OP_LE: {
++      OPCODE_TARGET(LE) {
+         Protect(
+           if (lessequal(L, RKB(i), RKC(i)) == GETARG_A(i))
+             dojump(L, pc, GETARG_sBx(*pc));
+@@ -770,13 +824,13 @@ void luaV_execute (lua_State *L, int nex
+         pc++;
+         continue;
+       }
+-      case OP_TEST: {
++      OPCODE_TARGET(TEST) {
+         if (l_isfalse(ra) != GETARG_C(i))
+           dojump(L, pc, GETARG_sBx(*pc));
+         pc++;
+         continue;
+       }
+-      case OP_TESTSET: {
++      OPCODE_TARGET(TESTSET) {
+         TValue *rb = RB(i);
+         if (l_isfalse(rb) != GETARG_C(i)) {
+           setobjs2s(L, ra, rb);
+@@ -785,7 +839,7 @@ void luaV_execute (lua_State *L, int nex
+         pc++;
+         continue;
+       }
+-      case OP_CALL: {
++      OPCODE_TARGET(CALL) {
+         int b = GETARG_B(i);
+         int nresults = GETARG_C(i) - 1;
+         if (b != 0) L->top = ra+b;  /* else previous instruction set top */
+@@ -806,7 +860,7 @@ void luaV_execute (lua_State *L, int nex
+           }
+         }
+       }
+-      case OP_TAILCALL: {
++      OPCODE_TARGET(TAILCALL) {
+         int b = GETARG_B(i);
+         if (b != 0) L->top = ra+b;  /* else previous instruction set top */
+         L->savedpc = pc;
+@@ -838,7 +892,7 @@ void luaV_execute (lua_State *L, int nex
+           }
+         }
+       }
+-      case OP_RETURN: {
++      OPCODE_TARGET(RETURN) {
+         int b = GETARG_B(i);
+         if (b != 0) L->top = ra+b-1;
+         if (L->openupval) luaF_close(L, base);
+@@ -853,7 +907,7 @@ void luaV_execute (lua_State *L, int nex
+           goto reentry;
+         }
+       }
+-      case OP_FORLOOP: {
++      OPCODE_TARGET(FORLOOP) {
+         /* If start,step and limit are all integers, we don't need to check
+          * against overflow in the looping.
+          */
+@@ -881,7 +935,7 @@ void luaV_execute (lua_State *L, int nex
+         }
+         continue;
+       }
+-      case OP_FORPREP: {
++      OPCODE_TARGET(FORPREP) {
+         const TValue *init = ra;
+         const TValue *plimit = ra+1;
+         const TValue *pstep = ra+2;
+@@ -904,7 +958,7 @@ void luaV_execute (lua_State *L, int nex
+         dojump(L, pc, GETARG_sBx(i));
+         continue;
+       }
+-      case OP_TFORLOOP: {
++      OPCODE_TARGET(TFORLOOP) {
+         StkId cb = ra + 3;  /* call base */
+         setobjs2s(L, cb+2, ra+2);
+         setobjs2s(L, cb+1, ra+1);
+@@ -920,7 +974,7 @@ void luaV_execute (lua_State *L, int nex
+         pc++;
+         continue;
+       }
+-      case OP_SETLIST: {
++      OPCODE_TARGET(SETLIST) {
+         int n = GETARG_B(i);
+         int c = GETARG_C(i);
+         int last;
+@@ -942,11 +996,11 @@ void luaV_execute (lua_State *L, int nex
+         }
+         continue;
+       }
+-      case OP_CLOSE: {
++      OPCODE_TARGET(CLOSE) {
+         luaF_close(L, ra);
+         continue;
+       }
+-      case OP_CLOSURE: {
++      OPCODE_TARGET(CLOSURE) {
+         Proto *p;
+         Closure *ncl;
+         int nup, j;
+@@ -966,7 +1020,7 @@ void luaV_execute (lua_State *L, int nex
+         Protect(luaC_checkGC(L));
+         continue;
+       }
+-      case OP_VARARG: {
++      OPCODE_TARGET(VARARG) {
+         int b = GETARG_B(i) - 1;
+         int j;
+         CallInfo *ci = L->ci;
diff --git a/package/utils/lua/patches/400-CVE-2014-5461.patch b/package/utils/lua/patches/400-CVE-2014-5461.patch
new file mode 100644
index 0000000..cce73ff
--- /dev/null
+++ b/package/utils/lua/patches/400-CVE-2014-5461.patch
@@ -0,0 +1,19 @@
+From: Enrico Tassi <gareuselesinge@debian.org>
+Date: Tue, 26 Aug 2014 16:20:55 +0200
+Subject: Fix stack overflow in vararg functions
+
+---
+ src/ldo.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/src/ldo.c
++++ b/src/ldo.c
+@@ -274,7 +274,7 @@ int luaD_precall (lua_State *L, StkId fu
+     CallInfo *ci;
+     StkId st, base;
+     Proto *p = cl->p;
+-    luaD_checkstack(L, p->maxstacksize);
++    luaD_checkstack(L, p->maxstacksize + p->numparams);
+     func = restorestack(L, funcr);
+     if (!p->is_vararg) {  /* no varargs? */
+       base = func + 1;
diff --git a/package/utils/lua5.3/Makefile b/package/utils/lua5.3/Makefile
new file mode 100644
index 0000000..405fa90
--- /dev/null
+++ b/package/utils/lua5.3/Makefile
@@ -0,0 +1,152 @@
+#
+# Copyright (C) 2006-2014 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=lua
+PKG_VERSION:=5.3.5
+PKG_RELEASE:=6
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://www.lua.org/ftp/ \
+	https://www.tecgraf.puc-rio.br/lua/ftp/
+PKG_HASH:=0c2eed3f960446e1a3e4b9a1ca2f3ff893b6ce41942cf54d5dd59ab4b3b058ac
+PKG_BUILD_PARALLEL:=1
+
+PKG_LICENSE:=MIT
+PKG_LICENSE_FILES:=COPYRIGHT
+PKG_CPE_ID:=cpe:/a:lua:lua
+
+HOST_PATCH_DIR := ./patches-host
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/host-build.mk
+
+define Package/lua5.3/Default
+  SUBMENU:=Lua
+  SECTION:=lang
+  CATEGORY:=Languages
+  TITLE:=Lua programming language (version 5.3)
+  URL:=https://www.lua.org/
+  MAINTAINER:=Jo-Philipp Wich <jo@mein.io>
+endef
+
+define Package/lua5.3/Default/description
+  Lua is a powerful, efficient, lightweight, embeddable scripting language. It
+  supports procedural programming, object-oriented programming, functional
+  programming, data-driven programming, and data description.
+endef
+
+define Package/liblua5.3
+$(call Package/lua5.3/Default)
+  SUBMENU:=
+  SECTION:=libs
+  CATEGORY:=Libraries
+  TITLE+= (libraries)
+  ABI_VERSION:=5.3
+endef
+
+define Package/liblua5.3/description
+$(call Package/lua5.3/Default/description)
+ This package contains the Lua shared libraries, needed by other programs.
+endef
+
+define Package/lua5.3
+$(call Package/lua5.3/Default)
+  DEPENDS:=+liblua5.3
+  TITLE+= (interpreter)
+endef
+
+define Package/lua5.3/description
+$(call Package/lua5.3/Default/description)
+  This package contains the Lua language interpreter.
+endef
+
+define Package/luac5.3
+$(call Package/lua5.3/Default)
+  DEPENDS:=+liblua5.3
+  TITLE+= (compiler)
+endef
+
+define Package/luac5.3/description
+$(call Package/lua5.3/Default/description)
+  This package contains the Lua language compiler.
+endef
+
+TARGET_CFLAGS += -DLUA_USE_LINUX $(FPIC) -std=gnu99
+
+define Build/Compile
+	$(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR) \
+		CC="$(TARGET_CROSS)gcc" \
+		AR="$(TARGET_CROSS)ar rcu" \
+		RANLIB="$(TARGET_CROSS)ranlib" \
+		INSTALL_ROOT=/usr \
+		CFLAGS="$(TARGET_CPPFLAGS) $(TARGET_CFLAGS)" \
+		PKG_VERSION=$(PKG_VERSION) \
+		linux
+	rm -rf $(PKG_INSTALL_DIR)
+	mkdir -p $(PKG_INSTALL_DIR)
+	$(MAKE) -C $(PKG_BUILD_DIR) \
+		INSTALL_TOP="$(PKG_INSTALL_DIR)/usr" \
+		install
+endef
+
+define Host/Configure
+	$(SED) 's,"/usr/local/","$(STAGING_DIR_HOSTPKG)/",' $(HOST_BUILD_DIR)/src/luaconf.h
+endef
+
+ifeq ($(HOST_OS),Darwin)
+	LUA_OS:=macosx
+else
+	ifeq ($(HOST_OS),FreeBSD)
+		LUA_OS:=freebsd
+	else
+		LUA_OS:=linux
+	endif
+endif
+
+define Host/Compile
+	$(MAKE) -C $(HOST_BUILD_DIR) \
+		CC="$(HOSTCC) $(HOST_FPIC) -std=gnu99" \
+		$(LUA_OS)
+endef
+
+define Host/Install
+	$(MAKE) -C $(HOST_BUILD_DIR) \
+		INSTALL_TOP="$(STAGING_DIR_HOSTPKG)" \
+		install
+endef
+
+define Build/InstallDev
+	$(INSTALL_DIR) $(1)/usr/include/lua5.3 $(1)/usr/lib
+	$(CP) $(PKG_INSTALL_DIR)/usr/include/lua5.3/lua{,lib,conf}.h $(1)/usr/include/lua5.3/
+	$(CP) $(PKG_INSTALL_DIR)/usr/include/lua5.3/lua.hpp $(1)/usr/include/lua5.3/
+	$(CP) $(PKG_INSTALL_DIR)/usr/include/lua5.3/lauxlib.h $(1)/usr/include/lua5.3/
+	$(INSTALL_DIR) $(1)/usr/lib
+	$(CP) $(PKG_INSTALL_DIR)/usr/lib/liblua5.3.{a,so*} $(1)/usr/lib/
+	$(LN) liblua5.3.so.0.0.0 $(1)/usr/lib/liblualib5.3.so
+endef
+
+define Package/liblua5.3/install
+	$(INSTALL_DIR) $(1)/usr/lib
+	$(CP) $(PKG_INSTALL_DIR)/usr/lib/liblua5.3.so* $(1)/usr/lib/
+endef
+
+define Package/lua5.3/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/lua5.3 $(1)/usr/bin/
+endef
+
+define Package/luac5.3/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/luac5.3 $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,liblua5.3))
+$(eval $(call BuildPackage,lua5.3))
+$(eval $(call BuildPackage,luac5.3))
+$(eval $(call HostBuild))
diff --git a/package/utils/lua5.3/patches-host/001-include-version-number.patch b/package/utils/lua5.3/patches-host/001-include-version-number.patch
new file mode 100644
index 0000000..1c9fdb2
--- /dev/null
+++ b/package/utils/lua5.3/patches-host/001-include-version-number.patch
@@ -0,0 +1,75 @@
+From 96576b44a1b368bd6590eb0778ae45cc9ccede3f Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
+Date: Fri, 21 Jun 2019 14:08:38 +0200
+Subject: [PATCH] include version number
+
+Including it allows multiple lua versions to coexist.
+
+Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
+---
+
+--- a/Makefile
++++ b/Makefile
+@@ -12,7 +12,7 @@ PLAT= none
+ # LUA_ROOT, LUA_LDIR, and LUA_CDIR in luaconf.h.
+ INSTALL_TOP= /usr/local
+ INSTALL_BIN= $(INSTALL_TOP)/bin
+-INSTALL_INC= $(INSTALL_TOP)/include
++INSTALL_INC= $(INSTALL_TOP)/include/lua$V
+ INSTALL_LIB= $(INSTALL_TOP)/lib
+ INSTALL_MAN= $(INSTALL_TOP)/man/man1
+ INSTALL_LMOD= $(INSTALL_TOP)/share/lua/$V
+@@ -39,10 +39,10 @@ RM= rm -f
+ PLATS= aix bsd c89 freebsd generic linux macosx mingw posix solaris
+ 
+ # What to install.
+-TO_BIN= lua luac
++TO_BIN= lua$V luac$V
+ TO_INC= lua.h luaconf.h lualib.h lauxlib.h lua.hpp
+-TO_LIB= liblua.a
+-TO_MAN= lua.1 luac.1
++TO_LIB= liblua$V.a
++TO_MAN= lua$V.1 luac$V.1
+ 
+ # Lua version and release.
+ V= 5.3
+@@ -52,7 +52,7 @@ R= $V.4
+ all:	$(PLAT)
+ 
+ $(PLATS) clean:
+-	cd src && $(MAKE) $@
++	cd src && $(MAKE) $@ V=$V
+ 
+ test:	dummy
+ 	src/lua -v
+diff --git a/doc/lua.1 b/doc/lua5.3.1
+rename from doc/lua.1
+rename to doc/lua5.3.1
+diff --git a/doc/luac.1 b/doc/luac5.3.1
+rename from doc/luac.1
+rename to doc/luac5.3.1
+diff --git a/src/Makefile b/src/Makefile
+--- a/src/Makefile
++++ b/src/Makefile
+@@ -28,7 +28,7 @@ MYOBJS=
+ 
+ PLATS= aix bsd c89 freebsd generic linux macosx mingw posix solaris
+ 
+-LUA_A=	liblua.a
++LUA_A=	liblua$V.a
+ CORE_O=	lapi.o lcode.o lctype.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o \
+ 	lmem.o lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o \
+ 	ltm.o lundump.o lvm.o lzio.o
+@@ -36,10 +36,10 @@ LIB_O=	lauxlib.o lbaselib.o lbitlib.o lc
+ 	lmathlib.o loslib.o lstrlib.o ltablib.o lutf8lib.o loadlib.o linit.o
+ BASE_O= $(CORE_O) $(LIB_O) $(MYOBJS)
+ 
+-LUA_T=	lua
++LUA_T=	lua$V
+ LUA_O=	lua.o
+ 
+-LUAC_T=	luac
++LUAC_T=	luac$V
+ LUAC_O=	luac.o
+ 
+ ALL_O= $(BASE_O) $(LUA_O) $(LUAC_O)
diff --git a/package/utils/lua5.3/patches-host/100-no_readline.patch b/package/utils/lua5.3/patches-host/100-no_readline.patch
new file mode 100644
index 0000000..bb014c5
--- /dev/null
+++ b/package/utils/lua5.3/patches-host/100-no_readline.patch
@@ -0,0 +1,54 @@
+--- a/src/luaconf.h
++++ b/src/luaconf.h
+@@ -61,14 +61,12 @@
+ #if defined(LUA_USE_LINUX)
+ #define LUA_USE_POSIX
+ #define LUA_USE_DLOPEN		/* needs an extra library: -ldl */
+-#define LUA_USE_READLINE	/* needs some extra libraries */
+ #endif
+ 
+ 
+ #if defined(LUA_USE_MACOSX)
+ #define LUA_USE_POSIX
+ #define LUA_USE_DLOPEN		/* MacOS does not need -ldl */
+-#define LUA_USE_READLINE	/* needs an extra library: -lreadline */
+ #endif
+ 
+ 
+--- a/src/Makefile
++++ b/src/Makefile
+@@ -23,6 +23,7 @@ MYCFLAGS=
+ MYLDFLAGS=
+ MYLIBS=
+ MYOBJS=
++# USE_READLINE=1
+ 
+ # == END OF USER SETTINGS -- NO NEED TO CHANGE ANYTHING BELOW THIS LINE =======
+ 
+@@ -83,6 +84,7 @@ echo:
+ 
+ # Convenience targets for popular platforms
+ ALL= all
++RFLAG=$(if $(USE_READLINE),-DLUA_USE_READLINE)
+ 
+ none:
+ 	@echo "Please do 'make PLATFORM' where PLATFORM is one of these:"
+@@ -102,15 +104,15 @@ c89:
+ 
+ 
+ freebsd:
+-	$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX -DLUA_USE_READLINE -I/usr/include/edit" SYSLIBS="-Wl,-E -ledit" CC="cc"
++	$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX $(RFLAG) -I/usr/include/edit" SYSLIBS="-Wl,-E -ledit" CC="cc"
+ 
+ generic: $(ALL)
+ 
+ linux:
+-	$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX" SYSLIBS="-Wl,-E -ldl -lreadline"
++	$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX" $(RFLAG) SYSLIBS="-Wl,-E -ldl $(if $(USE_READLINE), -lreadline)"
+ 
+ macosx:
+-	$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_MACOSX" SYSLIBS="-lreadline"
++	$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_MACOSX" $(RFLAG) SYSLIBS="$(if $(USE_READLINE), -lreadline)"
+ 
+ mingw:
+ 	$(MAKE) "LUA_A=lua53.dll" "LUA_T=lua.exe" \
diff --git a/package/utils/lua5.3/patches-host/200-CVE-2019-6706.patch b/package/utils/lua5.3/patches-host/200-CVE-2019-6706.patch
new file mode 100644
index 0000000..8024d41
--- /dev/null
+++ b/package/utils/lua5.3/patches-host/200-CVE-2019-6706.patch
@@ -0,0 +1,51 @@
+From 89aee84cbc9224f638f3b7951b306d2ee8ecb71e Mon Sep 17 00:00:00 2001
+From: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
+Date: Wed, 27 Mar 2019 14:30:12 -0300
+Subject: [PATCH] Fixed bug in 'lua_upvaluejoin'
+
+Bug-fix: joining an upvalue with itself could cause a use-after-free
+crash.
+---
+ src/lapi.c   | 12 +++++------
+ 1 file changed, 41 insertions(+), 39 deletions(-)
+
+--- a/src/lapi.c
++++ b/src/lapi.c
+@@ -1254,13 +1254,12 @@ LUA_API const char *lua_setupvalue (lua_
+ }
+ 
+ 
+-static UpVal **getupvalref (lua_State *L, int fidx, int n, LClosure **pf) {
++static UpVal **getupvalref (lua_State *L, int fidx, int n) {
+   LClosure *f;
+   StkId fi = index2addr(L, fidx);
+   api_check(L, ttisLclosure(fi), "Lua function expected");
+   f = clLvalue(fi);
+   api_check(L, (1 <= n && n <= f->p->sizeupvalues), "invalid upvalue index");
+-  if (pf) *pf = f;
+   return &f->upvals[n - 1];  /* get its upvalue pointer */
+ }
+ 
+@@ -1269,7 +1268,7 @@ LUA_API void *lua_upvalueid (lua_State *
+   StkId fi = index2addr(L, fidx);
+   switch (ttype(fi)) {
+     case LUA_TLCL: {  /* lua closure */
+-      return *getupvalref(L, fidx, n, NULL);
++      return *getupvalref(L, fidx, n);
+     }
+     case LUA_TCCL: {  /* C closure */
+       CClosure *f = clCvalue(fi);
+@@ -1286,9 +1285,10 @@ LUA_API void *lua_upvalueid (lua_State *
+ 
+ LUA_API void lua_upvaluejoin (lua_State *L, int fidx1, int n1,
+                                             int fidx2, int n2) {
+-  LClosure *f1;
+-  UpVal **up1 = getupvalref(L, fidx1, n1, &f1);
+-  UpVal **up2 = getupvalref(L, fidx2, n2, NULL);
++  UpVal **up1 = getupvalref(L, fidx1, n1);
++  UpVal **up2 = getupvalref(L, fidx2, n2);
++  if (*up1 == *up2)
++    return;
+   luaC_upvdeccount(L, *up1);
+   *up1 = *up2;
+   (*up1)->refcount++;
diff --git a/package/utils/lua5.3/patches/001-include-version-number.patch b/package/utils/lua5.3/patches/001-include-version-number.patch
new file mode 100644
index 0000000..1c9fdb2
--- /dev/null
+++ b/package/utils/lua5.3/patches/001-include-version-number.patch
@@ -0,0 +1,75 @@
+From 96576b44a1b368bd6590eb0778ae45cc9ccede3f Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
+Date: Fri, 21 Jun 2019 14:08:38 +0200
+Subject: [PATCH] include version number
+
+Including it allows multiple lua versions to coexist.
+
+Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
+---
+
+--- a/Makefile
++++ b/Makefile
+@@ -12,7 +12,7 @@ PLAT= none
+ # LUA_ROOT, LUA_LDIR, and LUA_CDIR in luaconf.h.
+ INSTALL_TOP= /usr/local
+ INSTALL_BIN= $(INSTALL_TOP)/bin
+-INSTALL_INC= $(INSTALL_TOP)/include
++INSTALL_INC= $(INSTALL_TOP)/include/lua$V
+ INSTALL_LIB= $(INSTALL_TOP)/lib
+ INSTALL_MAN= $(INSTALL_TOP)/man/man1
+ INSTALL_LMOD= $(INSTALL_TOP)/share/lua/$V
+@@ -39,10 +39,10 @@ RM= rm -f
+ PLATS= aix bsd c89 freebsd generic linux macosx mingw posix solaris
+ 
+ # What to install.
+-TO_BIN= lua luac
++TO_BIN= lua$V luac$V
+ TO_INC= lua.h luaconf.h lualib.h lauxlib.h lua.hpp
+-TO_LIB= liblua.a
+-TO_MAN= lua.1 luac.1
++TO_LIB= liblua$V.a
++TO_MAN= lua$V.1 luac$V.1
+ 
+ # Lua version and release.
+ V= 5.3
+@@ -52,7 +52,7 @@ R= $V.4
+ all:	$(PLAT)
+ 
+ $(PLATS) clean:
+-	cd src && $(MAKE) $@
++	cd src && $(MAKE) $@ V=$V
+ 
+ test:	dummy
+ 	src/lua -v
+diff --git a/doc/lua.1 b/doc/lua5.3.1
+rename from doc/lua.1
+rename to doc/lua5.3.1
+diff --git a/doc/luac.1 b/doc/luac5.3.1
+rename from doc/luac.1
+rename to doc/luac5.3.1
+diff --git a/src/Makefile b/src/Makefile
+--- a/src/Makefile
++++ b/src/Makefile
+@@ -28,7 +28,7 @@ MYOBJS=
+ 
+ PLATS= aix bsd c89 freebsd generic linux macosx mingw posix solaris
+ 
+-LUA_A=	liblua.a
++LUA_A=	liblua$V.a
+ CORE_O=	lapi.o lcode.o lctype.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o \
+ 	lmem.o lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o \
+ 	ltm.o lundump.o lvm.o lzio.o
+@@ -36,10 +36,10 @@ LIB_O=	lauxlib.o lbaselib.o lbitlib.o lc
+ 	lmathlib.o loslib.o lstrlib.o ltablib.o lutf8lib.o loadlib.o linit.o
+ BASE_O= $(CORE_O) $(LIB_O) $(MYOBJS)
+ 
+-LUA_T=	lua
++LUA_T=	lua$V
+ LUA_O=	lua.o
+ 
+-LUAC_T=	luac
++LUAC_T=	luac$V
+ LUAC_O=	luac.o
+ 
+ ALL_O= $(BASE_O) $(LUA_O) $(LUAC_O)
diff --git a/package/utils/lua5.3/patches/020-shared_liblua.patch b/package/utils/lua5.3/patches/020-shared_liblua.patch
new file mode 100644
index 0000000..a462fa4
--- /dev/null
+++ b/package/utils/lua5.3/patches/020-shared_liblua.patch
@@ -0,0 +1,322 @@
+--- a/Makefile
++++ b/Makefile
+@@ -41,7 +41,7 @@ PLATS= aix bsd c89 freebsd generic linux
+ # What to install.
+ TO_BIN= lua$V luac$V
+ TO_INC= lua.h luaconf.h lualib.h lauxlib.h lua.hpp
+-TO_LIB= liblua$V.a
++TO_LIB= liblua$V.a liblua$V.so.0.0.0
+ TO_MAN= lua$V.1 luac$V.1
+ 
+ # Lua version and release.
+@@ -62,6 +62,9 @@ install: dummy
+ 	cd src && $(INSTALL_EXEC) $(TO_BIN) $(INSTALL_BIN)
+ 	cd src && $(INSTALL_DATA) $(TO_INC) $(INSTALL_INC)
+ 	cd src && $(INSTALL_DATA) $(TO_LIB) $(INSTALL_LIB)
++	ln -s liblua$V.so.0.0.0 $(INSTALL_LIB)/liblua$V.so.0.0
++	ln -s liblua$V.so.0.0.0 $(INSTALL_LIB)/liblua$V.so.0
++	ln -s liblua$V.so.0.0.0 $(INSTALL_LIB)/liblua$V.so
+ 	cd doc && $(INSTALL_DATA) $(TO_MAN) $(INSTALL_MAN)
+ 
+ uninstall:
+--- a/src/ldo.h
++++ b/src/ldo.h
+@@ -47,8 +47,8 @@ LUAI_FUNC int luaD_pcall (lua_State *L,
+ LUAI_FUNC int luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult,
+                                           int nres);
+ LUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize);
+-LUAI_FUNC void luaD_growstack (lua_State *L, int n);
+-LUAI_FUNC void luaD_shrinkstack (lua_State *L);
++LUA_API void luaD_growstack (lua_State *L, int n);
++LUA_API void luaD_shrinkstack (lua_State *L);
+ LUAI_FUNC void luaD_inctop (lua_State *L);
+ 
+ LUAI_FUNC l_noret luaD_throw (lua_State *L, int errcode);
+--- a/src/lfunc.h
++++ b/src/lfunc.h
+@@ -47,14 +47,14 @@ struct UpVal {
+ #define upisopen(up)	((up)->v != &(up)->u.value)
+ 
+ 
+-LUAI_FUNC Proto *luaF_newproto (lua_State *L);
++LUA_API Proto *luaF_newproto (lua_State *L);
+ LUAI_FUNC CClosure *luaF_newCclosure (lua_State *L, int nelems);
+-LUAI_FUNC LClosure *luaF_newLclosure (lua_State *L, int nelems);
+-LUAI_FUNC void luaF_initupvals (lua_State *L, LClosure *cl);
+-LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level);
+-LUAI_FUNC void luaF_close (lua_State *L, StkId level);
++LUA_API LClosure *luaF_newLclosure (lua_State *L, int nelems);
++LUA_API void luaF_initupvals (lua_State *L, LClosure *cl);
++LUA_API UpVal *luaF_findupval (lua_State *L, StkId level);
++LUA_API void luaF_close (lua_State *L, StkId level);
+ LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f);
+-LUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number,
++LUA_API const char *luaF_getlocalname (const Proto *func, int local_number,
+                                          int pc);
+ 
+ 
+--- a/src/lgc.h
++++ b/src/lgc.h
+@@ -133,11 +133,11 @@
+ 
+ LUAI_FUNC void luaC_fix (lua_State *L, GCObject *o);
+ LUAI_FUNC void luaC_freeallobjects (lua_State *L);
+-LUAI_FUNC void luaC_step (lua_State *L);
++LUA_API void luaC_step (lua_State *L);
+ LUAI_FUNC void luaC_runtilstate (lua_State *L, int statesmask);
+ LUAI_FUNC void luaC_fullgc (lua_State *L, int isemergency);
+ LUAI_FUNC GCObject *luaC_newobj (lua_State *L, int tt, size_t sz);
+-LUAI_FUNC void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v);
++LUA_API void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v);
+ LUAI_FUNC void luaC_barrierback_ (lua_State *L, Table *o);
+ LUAI_FUNC void luaC_upvalbarrier_ (lua_State *L, UpVal *uv);
+ LUAI_FUNC void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt);
+--- a/src/llex.h
++++ b/src/llex.h
+@@ -73,13 +73,13 @@ typedef struct LexState {
+ 
+ 
+ LUAI_FUNC void luaX_init (lua_State *L);
+-LUAI_FUNC void luaX_setinput (lua_State *L, LexState *ls, ZIO *z,
++LUA_API void luaX_setinput (lua_State *L, LexState *ls, ZIO *z,
+                               TString *source, int firstchar);
+ LUAI_FUNC TString *luaX_newstring (LexState *ls, const char *str, size_t l);
+-LUAI_FUNC void luaX_next (LexState *ls);
+-LUAI_FUNC int luaX_lookahead (LexState *ls);
+-LUAI_FUNC l_noret luaX_syntaxerror (LexState *ls, const char *s);
+-LUAI_FUNC const char *luaX_token2str (LexState *ls, int token);
++LUA_API void luaX_next (LexState *ls);
++LUA_API int luaX_lookahead (LexState *ls);
++LUA_API l_noret luaX_syntaxerror (LexState *ls, const char *s);
++LUA_API const char *luaX_token2str (LexState *ls, int token);
+ 
+ 
+ #endif
+--- a/src/lmem.h
++++ b/src/lmem.h
+@@ -56,12 +56,12 @@
+ #define luaM_reallocvector(L, v,oldn,n,t) \
+    ((v)=cast(t *, luaM_reallocv(L, v, oldn, n, sizeof(t))))
+ 
+-LUAI_FUNC l_noret luaM_toobig (lua_State *L);
++LUA_API l_noret luaM_toobig (lua_State *L);
+ 
+ /* not to be called directly */
+-LUAI_FUNC void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize,
++LUA_API void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize,
+                                                           size_t size);
+-LUAI_FUNC void *luaM_growaux_ (lua_State *L, void *block, int *size,
++LUA_API void *luaM_growaux_ (lua_State *L, void *block, int *size,
+                                size_t size_elem, int limit,
+                                const char *what);
+ 
+--- a/src/lobject.h
++++ b/src/lobject.h
+@@ -525,7 +525,7 @@ typedef struct Table {
+ #define luaO_nilobject		(&luaO_nilobject_)
+ 
+ 
+-LUAI_DDEC const TValue luaO_nilobject_;
++LUA_API const TValue luaO_nilobject_;
+ 
+ /* size of buffer for 'luaO_utf8esc' function */
+ #define UTF8BUFFSZ	8
+@@ -534,15 +534,15 @@ LUAI_FUNC int luaO_int2fb (unsigned int
+ LUAI_FUNC int luaO_fb2int (int x);
+ LUAI_FUNC int luaO_utf8esc (char *buff, unsigned long x);
+ LUAI_FUNC int luaO_ceillog2 (unsigned int x);
+-LUAI_FUNC void luaO_arith (lua_State *L, int op, const TValue *p1,
++LUA_API void luaO_arith (lua_State *L, int op, const TValue *p1,
+                            const TValue *p2, TValue *res);
+ LUAI_FUNC size_t luaO_str2num (const char *s, TValue *o);
+ LUAI_FUNC int luaO_hexavalue (int c);
+ LUAI_FUNC void luaO_tostring (lua_State *L, StkId obj);
+-LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt,
++LUA_API const char *luaO_pushvfstring (lua_State *L, const char *fmt,
+                                                        va_list argp);
+-LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...);
+-LUAI_FUNC void luaO_chunkid (char *out, const char *source, size_t len);
++LUA_API const char *luaO_pushfstring (lua_State *L, const char *fmt, ...);
++LUA_API void luaO_chunkid (char *out, const char *source, size_t len);
+ 
+ 
+ #endif
+--- a/src/lopcodes.h
++++ b/src/lopcodes.h
+@@ -278,7 +278,7 @@ enum OpArgMask {
+   OpArgK   /* argument is a constant or register/constant */
+ };
+ 
+-LUAI_DDEC const lu_byte luaP_opmodes[NUM_OPCODES];
++LUA_API const lu_byte luaP_opmodes[NUM_OPCODES];
+ 
+ #define getOpMode(m)	(cast(enum OpMode, luaP_opmodes[m] & 3))
+ #define getBMode(m)	(cast(enum OpArgMask, (luaP_opmodes[m] >> 4) & 3))
+@@ -287,7 +287,7 @@ LUAI_DDEC const lu_byte luaP_opmodes[NUM
+ #define testTMode(m)	(luaP_opmodes[m] & (1 << 7))
+ 
+ 
+-LUAI_DDEC const char *const luaP_opnames[NUM_OPCODES+1];  /* opcode names */
++LUA_API const char *const luaP_opnames[NUM_OPCODES+1];  /* opcode names */
+ 
+ 
+ /* number of list items to accumulate before a SETLIST instruction */
+--- a/src/lstate.h
++++ b/src/lstate.h
+@@ -244,9 +244,9 @@ union GCUnion {
+ 
+ LUAI_FUNC void luaE_setdebt (global_State *g, l_mem debt);
+ LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1);
+-LUAI_FUNC CallInfo *luaE_extendCI (lua_State *L);
+-LUAI_FUNC void luaE_freeCI (lua_State *L);
+-LUAI_FUNC void luaE_shrinkCI (lua_State *L);
++LUA_API CallInfo *luaE_extendCI (lua_State *L);
++LUA_API void luaE_freeCI (lua_State *L);
++LUA_API void luaE_shrinkCI (lua_State *L);
+ 
+ 
+ #endif
+--- a/src/lstring.h
++++ b/src/lstring.h
+@@ -35,15 +35,15 @@
+ 
+ LUAI_FUNC unsigned int luaS_hash (const char *str, size_t l, unsigned int seed);
+ LUAI_FUNC unsigned int luaS_hashlongstr (TString *ts);
+-LUAI_FUNC int luaS_eqlngstr (TString *a, TString *b);
++LUA_API int luaS_eqlngstr (TString *a, TString *b);
+ LUAI_FUNC void luaS_resize (lua_State *L, int newsize);
+ LUAI_FUNC void luaS_clearcache (global_State *g);
+ LUAI_FUNC void luaS_init (lua_State *L);
+ LUAI_FUNC void luaS_remove (lua_State *L, TString *ts);
+ LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s);
+-LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l);
+-LUAI_FUNC TString *luaS_new (lua_State *L, const char *str);
+-LUAI_FUNC TString *luaS_createlngstrobj (lua_State *L, size_t l);
++LUA_API TString *luaS_newlstr (lua_State *L, const char *str, size_t l);
++LUA_API TString *luaS_new (lua_State *L, const char *str);
++LUA_API TString *luaS_createlngstrobj (lua_State *L, size_t l);
+ 
+ 
+ #endif
+--- a/src/ltable.h
++++ b/src/ltable.h
+@@ -41,14 +41,14 @@
+ 
+ 
+ LUAI_FUNC const TValue *luaH_getint (Table *t, lua_Integer key);
+-LUAI_FUNC void luaH_setint (lua_State *L, Table *t, lua_Integer key,
++LUA_API void luaH_setint (lua_State *L, Table *t, lua_Integer key,
+                                                     TValue *value);
+ LUAI_FUNC const TValue *luaH_getshortstr (Table *t, TString *key);
+ LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key);
+ LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key);
+ LUAI_FUNC TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key);
+-LUAI_FUNC TValue *luaH_set (lua_State *L, Table *t, const TValue *key);
+-LUAI_FUNC Table *luaH_new (lua_State *L);
++LUA_API TValue *luaH_set (lua_State *L, Table *t, const TValue *key);
++LUA_API Table *luaH_new (lua_State *L);
+ LUAI_FUNC void luaH_resize (lua_State *L, Table *t, unsigned int nasize,
+                                                     unsigned int nhsize);
+ LUAI_FUNC void luaH_resizearray (lua_State *L, Table *t, unsigned int nasize);
+--- a/src/ltm.h
++++ b/src/ltm.h
+@@ -55,10 +55,10 @@ typedef enum {
+ LUAI_DDEC const char *const luaT_typenames_[LUA_TOTALTAGS];
+ 
+ 
+-LUAI_FUNC const char *luaT_objtypename (lua_State *L, const TValue *o);
++LUA_API const char *luaT_objtypename (lua_State *L, const TValue *o);
+ 
+ LUAI_FUNC const TValue *luaT_gettm (Table *events, TMS event, TString *ename);
+-LUAI_FUNC const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o,
++LUA_API const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o,
+                                                        TMS event);
+ LUAI_FUNC void luaT_init (lua_State *L);
+ 
+@@ -66,9 +66,9 @@ LUAI_FUNC void luaT_callTM (lua_State *L
+                             const TValue *p2, TValue *p3, int hasres);
+ LUAI_FUNC int luaT_callbinTM (lua_State *L, const TValue *p1, const TValue *p2,
+                               StkId res, TMS event);
+-LUAI_FUNC void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2,
++LUA_API void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2,
+                               StkId res, TMS event);
+-LUAI_FUNC int luaT_callorderTM (lua_State *L, const TValue *p1,
++LUA_API int luaT_callorderTM (lua_State *L, const TValue *p1,
+                                 const TValue *p2, TMS event);
+ 
+ 
+--- a/src/lundump.h
++++ b/src/lundump.h
+@@ -23,10 +23,10 @@
+ #define LUAC_FORMAT	0	/* this is the official format */
+ 
+ /* load one chunk; from lundump.c */
+-LUAI_FUNC LClosure* luaU_undump (lua_State* L, ZIO* Z, const char* name);
++LUA_API LClosure* luaU_undump (lua_State* L, ZIO* Z, const char* name);
+ 
+ /* dump one chunk; from ldump.c */
+-LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w,
++LUA_API int luaU_dump (lua_State* L, const Proto* f, lua_Writer w,
+                          void* data, int strip);
+ 
+ #endif
+--- a/src/lzio.h
++++ b/src/lzio.h
+@@ -61,6 +61,6 @@ struct Zio {
+ };
+ 
+ 
+-LUAI_FUNC int luaZ_fill (ZIO *z);
++LUA_API int luaZ_fill (ZIO *z);
+ 
+ #endif
+--- a/src/Makefile
++++ b/src/Makefile
+@@ -29,6 +29,7 @@ MYOBJS=
+ PLATS= aix bsd c89 freebsd generic linux macosx mingw posix solaris
+ 
+ LUA_A=	liblua$V.a
++LUA_SO=	liblua$V.so.0.0.0
+ CORE_O=	lapi.o lcode.o lctype.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o \
+ 	lmem.o lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o \
+ 	ltm.o lundump.o lvm.o lzio.o
+@@ -43,8 +44,9 @@ LUAC_T=	luac$V
+ LUAC_O=	luac.o
+ 
+ ALL_O= $(BASE_O) $(LUA_O) $(LUAC_O)
+-ALL_T= $(LUA_A) $(LUA_T) $(LUAC_T)
++ALL_T= $(LUA_A) $(LUA_SO) $(LUA_T) $(LUAC_T)
+ ALL_A= $(LUA_A)
++ALL_SO= $(LUA_SO)
+ 
+ # Targets start here.
+ default: $(PLAT)
+@@ -55,14 +57,25 @@ o:	$(ALL_O)
+ 
+ a:	$(ALL_A)
+ 
++so:	$(ALL_SO)
++
+ $(LUA_A): $(BASE_O)
+ 	$(AR) $@ $(BASE_O)
+ 	$(RANLIB) $@
+ 
+-$(LUA_T): $(LUA_O) $(LUA_A)
+-	$(CC) -o $@ $(LDFLAGS) $(LUA_O) $(LUA_A) $(LIBS)
++$(LUA_SO): $(CORE_O) $(LIB_O)
++	$(CC) -o $@ -Wl,-Bsymbolic-functions -shared -Wl,-soname="$@" $?
++	ln -fs $@ liblua$V.so.0.0
++	ln -fs $@ liblua$V.so.0
++	ln -fs $@ liblua$V.so
++
++$(LUA_T): $(LUA_O) $(LUA_SO)
++	$(CC) -o $@ -L. -llua$V $(MYLDFLAGS) $(LUA_O) $(LIBS)
++
++$(LUAC_T): $(LUAC_O) $(LUA_SO)
++	$(CC) -o $@ -L. -llua$V $(MYLDFLAGS) $(LUAC_O) $(LIBS)
+ 
+-$(LUAC_T): $(LUAC_O) $(LUA_A)
++$(LUAC_T)-host: $(LUAC_O) $(LUA_A)
+ 	$(CC) -o $@ $(LDFLAGS) $(LUAC_O) $(LUA_A) $(LIBS)
+ 
+ clean:
diff --git a/package/utils/lua5.3/patches/100-no_readline.patch b/package/utils/lua5.3/patches/100-no_readline.patch
new file mode 100644
index 0000000..363b900
--- /dev/null
+++ b/package/utils/lua5.3/patches/100-no_readline.patch
@@ -0,0 +1,54 @@
+--- a/src/luaconf.h
++++ b/src/luaconf.h
+@@ -61,14 +61,12 @@
+ #if defined(LUA_USE_LINUX)
+ #define LUA_USE_POSIX
+ #define LUA_USE_DLOPEN		/* needs an extra library: -ldl */
+-#define LUA_USE_READLINE	/* needs some extra libraries */
+ #endif
+ 
+ 
+ #if defined(LUA_USE_MACOSX)
+ #define LUA_USE_POSIX
+ #define LUA_USE_DLOPEN		/* MacOS does not need -ldl */
+-#define LUA_USE_READLINE	/* needs an extra library: -lreadline */
+ #endif
+ 
+ 
+--- a/src/Makefile
++++ b/src/Makefile
+@@ -23,6 +23,7 @@ MYCFLAGS=
+ MYLDFLAGS=
+ MYLIBS=
+ MYOBJS=
++# USE_READLINE=1
+ 
+ # == END OF USER SETTINGS -- NO NEED TO CHANGE ANYTHING BELOW THIS LINE =======
+ 
+@@ -96,6 +97,7 @@ echo:
+ 
+ # Convenience targets for popular platforms
+ ALL= all
++RFLAG=$(if $(USE_READLINE),-DLUA_USE_READLINE)
+ 
+ none:
+ 	@echo "Please do 'make PLATFORM' where PLATFORM is one of these:"
+@@ -115,15 +117,15 @@ c89:
+ 
+ 
+ freebsd:
+-	$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX -DLUA_USE_READLINE -I/usr/include/edit" SYSLIBS="-Wl,-E -ledit" CC="cc"
++	$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX $(RFLAG) -I/usr/include/edit" SYSLIBS="-Wl,-E -ledit" CC="cc"
+ 
+ generic: $(ALL)
+ 
+ linux:
+-	$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX" SYSLIBS="-Wl,-E -ldl -lreadline"
++	$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX" $(RFLAG) SYSLIBS="-Wl,-E -ldl $(if $(USE_READLINE), -lreadline)"
+ 
+ macosx:
+-	$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_MACOSX" SYSLIBS="-lreadline"
++	$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_MACOSX" $(RFLAG) SYSLIBS="$(if $(USE_READLINE), -lreadline)"
+ 
+ mingw:
+ 	$(MAKE) "LUA_A=lua53.dll" "LUA_T=lua.exe" \
diff --git a/package/utils/lua5.3/patches/200-CVE-2019-6706.patch b/package/utils/lua5.3/patches/200-CVE-2019-6706.patch
new file mode 100644
index 0000000..8024d41
--- /dev/null
+++ b/package/utils/lua5.3/patches/200-CVE-2019-6706.patch
@@ -0,0 +1,51 @@
+From 89aee84cbc9224f638f3b7951b306d2ee8ecb71e Mon Sep 17 00:00:00 2001
+From: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
+Date: Wed, 27 Mar 2019 14:30:12 -0300
+Subject: [PATCH] Fixed bug in 'lua_upvaluejoin'
+
+Bug-fix: joining an upvalue with itself could cause a use-after-free
+crash.
+---
+ src/lapi.c   | 12 +++++------
+ 1 file changed, 41 insertions(+), 39 deletions(-)
+
+--- a/src/lapi.c
++++ b/src/lapi.c
+@@ -1254,13 +1254,12 @@ LUA_API const char *lua_setupvalue (lua_
+ }
+ 
+ 
+-static UpVal **getupvalref (lua_State *L, int fidx, int n, LClosure **pf) {
++static UpVal **getupvalref (lua_State *L, int fidx, int n) {
+   LClosure *f;
+   StkId fi = index2addr(L, fidx);
+   api_check(L, ttisLclosure(fi), "Lua function expected");
+   f = clLvalue(fi);
+   api_check(L, (1 <= n && n <= f->p->sizeupvalues), "invalid upvalue index");
+-  if (pf) *pf = f;
+   return &f->upvals[n - 1];  /* get its upvalue pointer */
+ }
+ 
+@@ -1269,7 +1268,7 @@ LUA_API void *lua_upvalueid (lua_State *
+   StkId fi = index2addr(L, fidx);
+   switch (ttype(fi)) {
+     case LUA_TLCL: {  /* lua closure */
+-      return *getupvalref(L, fidx, n, NULL);
++      return *getupvalref(L, fidx, n);
+     }
+     case LUA_TCCL: {  /* C closure */
+       CClosure *f = clCvalue(fi);
+@@ -1286,9 +1285,10 @@ LUA_API void *lua_upvalueid (lua_State *
+ 
+ LUA_API void lua_upvaluejoin (lua_State *L, int fidx1, int n1,
+                                             int fidx2, int n2) {
+-  LClosure *f1;
+-  UpVal **up1 = getupvalref(L, fidx1, n1, &f1);
+-  UpVal **up2 = getupvalref(L, fidx2, n2, NULL);
++  UpVal **up1 = getupvalref(L, fidx1, n1);
++  UpVal **up2 = getupvalref(L, fidx2, n2);
++  if (*up1 == *up2)
++    return;
+   luaC_upvdeccount(L, *up1);
+   *up1 = *up2;
+   (*up1)->refcount++;
diff --git a/package/utils/mdadm/Makefile b/package/utils/mdadm/Makefile
new file mode 100644
index 0000000..b521daa
--- /dev/null
+++ b/package/utils/mdadm/Makefile
@@ -0,0 +1,74 @@
+#
+# Copyright (C) 2008-2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=mdadm
+PKG_VERSION:=4.3
+PKG_RELEASE:=2
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=@KERNEL/linux/utils/raid/mdadm
+PKG_HASH:=416727ae1f1080ea6e3090cea36dd076826fc369151e36ab736557ba92196f9f
+
+PKG_MAINTAINER:=Felix Fietkau <nbd@nbd.name>
+PKG_CPE_ID:=cpe:/a:mdadm_project:mdadm
+
+PKG_BUILD_PARALLEL:=1
+PKG_BUILD_FLAGS:=gc-sections
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/mdadm
+  SECTION:=utils
+  CATEGORY:=Utilities
+  SUBMENU:=Disc
+  TITLE:=A tool for managing Soft RAID under Linux
+  URL:=https://www.kernel.org/pub/linux/utils/raid/mdadm/
+  DEPENDS:=+libpthread +kmod-md-mod +kmod-md-raid0 +kmod-md-raid10 +kmod-md-raid1
+endef
+
+define Package/mdadm/description
+ A tool for managing Linux Software RAID arrays.
+ RAID 0, 1 and 10 support included.
+ If you need RAID 4,5 or 6 functionality please
+ install kmod-md-raid456 .
+endef
+
+define Package/mdadm/conffiles
+/etc/config/mdadm
+endef
+
+TARGET_CFLAGS += \
+	-DHAVE_STDINT_H -DNO_COROSYNC -DNO_DLM -DUSE_PTHREADS \
+	-DCONFFILE='\"/var/etc/mdadm.conf\"' \
+	-DMAP_DIR='\"/var/run/mdadm\"' \
+	-DMDMON_DIR='\"/var/run/mdadm\"' \
+	-DFAILED_SLOTS_DIR='\"/var/run/mdadm/failed-slots\"' \
+	-DNO_LIBUDEV \
+	-D_LARGEFILE64_SOURCE
+
+TARGET_CXFLAGS = -DNO_LIBUDEV
+
+MAKE_FLAGS += \
+		CHECK_RUN_DIR=0 \
+		CXFLAGS="$(TARGET_CXFLAGS)"
+
+define Build/Compile
+	$(call Build/Compile/Default,mdadm)
+endef
+
+define Package/mdadm/install
+	$(INSTALL_DIR) $(1)/sbin
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/mdadm $(1)/sbin
+	$(INSTALL_DIR) $(1)/etc/init.d
+	$(INSTALL_BIN) ./files/mdadm.init $(1)/etc/init.d/mdadm
+	$(INSTALL_DIR) $(1)/etc/config
+	$(INSTALL_CONF) ./files/mdadm.config $(1)/etc/config/mdadm
+endef
+
+$(eval $(call BuildPackage,mdadm))
diff --git a/package/utils/mdadm/files/mdadm.config b/package/utils/mdadm/files/mdadm.config
new file mode 100644
index 0000000..50afbc2
--- /dev/null
+++ b/package/utils/mdadm/files/mdadm.config
@@ -0,0 +1,18 @@
+config mdadm
+	option email root
+	# list devices /dev/hd*
+	# list devices /dev/sd*
+	# list devices partitions
+
+config array
+	option uuid 52c5c44a:d2162820:f75d3464:799750f8
+	option device /dev/md0
+	# option name raid:0
+	# option super_minor 0
+	# list devices /dev/sda1
+	# list devices /dev/sdb1
+	# option spares 0
+	# option spare_group spares
+	# option bitmap /bitmap.md
+	# option container 00000000:00000000:00000000:00000000
+	# option member 1
diff --git a/package/utils/mdadm/files/mdadm.init b/package/utils/mdadm/files/mdadm.init
new file mode 100644
index 0000000..64a50b3
--- /dev/null
+++ b/package/utils/mdadm/files/mdadm.init
@@ -0,0 +1,93 @@
+#!/bin/sh /etc/rc.common
+
+START=13
+STOP=98
+
+USE_PROCD=1
+PROG=/sbin/mdadm
+NAME=mdadm
+
+CONF="/var/etc/mdadm.conf"
+
+append_list_item() {
+	append "$2" "$1" "$3"
+}
+
+append_option() {
+	local var="$1"
+	local cfg="$2"
+	local opt="$3"
+	local name="$4"
+	local sep="$5"
+	local str
+
+	if [ -n "$sep" ]; then
+		config_list_foreach "$cfg" "$opt" append_list_item str "$sep"
+	else
+		config_get str "$cfg" "$opt"
+	fi
+
+	[ -n "$str" ] && append "$var" $(printf "%s=%s" "${name:-${opt//_/-}}" "$str")
+}
+
+mdadm_common() {
+	local cfg="$1"
+	local email devices
+
+	if [ -x /usr/sbin/sendmail ]; then
+		config_get email "$cfg" email
+		[ -n "$email" ] && printf "MAILADDR %s\n" "$email" >> $CONF
+	fi
+
+	config_list_foreach "$cfg" devices append_list_item devices " "
+	[ -n "$devices" ] && printf "DEVICE %s\n" "$devices" >> $CONF
+}
+
+mdadm_array() {
+	local cfg="$1"
+	local uuid device devices name array
+
+	config_get uuid "$cfg" uuid
+	config_get name "$cfg" name
+	config_get device "$cfg" device
+
+	if [ -z "$device" ] || [ -z "$uuid$name" ]; then
+		echo "Skipping array without device, uuid or name" >&2
+		return
+	fi
+
+	[ -n "$uuid" ] && append array "uuid=$uuid"
+	[ -n "$name" ] && append array "name=$name"
+
+	append_option array "$cfg" super_minor
+	append_option array "$cfg" spares
+	append_option array "$cfg" spare_group
+	append_option array "$cfg" bitmap
+	append_option array "$cfg" container
+	append_option array "$cfg" member
+	append_option array "$cfg" devices devices ","
+
+	printf "ARRAY %s %s\n" "$device" "$array" >> $CONF
+}
+
+start_service() {
+	local email
+
+	mkdir -p "${CONF%/*}"
+	printf "# Autogenerated from /etc/config/mdadm, do not edit!\n" > $CONF
+
+	config_load mdadm
+	config_foreach mdadm_common mdadm
+	config_foreach mdadm_array array
+
+	$PROG --assemble --scan --config="$CONF"
+
+	procd_open_instance
+	procd_set_param command "$PROG" --monitor --syslog --scan --config="$CONF"
+	procd_close_instance
+}
+
+stop_service() {
+	$PROG --stop --scan
+}
+
diff --git a/package/utils/mdadm/patches/010-falloc.patch b/package/utils/mdadm/patches/010-falloc.patch
new file mode 100644
index 0000000..2f2a9b8
--- /dev/null
+++ b/package/utils/mdadm/patches/010-falloc.patch
@@ -0,0 +1,36 @@
+From 52bead95d2957437c691891fcdc49bd6afccdd49 Mon Sep 17 00:00:00 2001
+From: Fabrice Fontaine <fontaine.fabrice@gmail.com>
+Date: Fri, 12 Apr 2024 18:45:13 +0200
+Subject: Create.c: fix uclibc build
+
+Define FALLOC_FL_ZERO_RANGE if needed as FALLOC_FL_ZERO_RANGE is only
+defined for aarch64 on uclibc-ng resulting in the following or1k build
+failure since commit 577fd10486d8d1472a6b559066f344ac30a3a391:
+
+Create.c: In function 'write_zeroes_fork':
+Create.c:155:35: error: 'FALLOC_FL_ZERO_RANGE' undeclared (first use in this function)
+  155 |                 if (fallocate(fd, FALLOC_FL_ZERO_RANGE | FALLOC_FL_KEEP_SIZE,
+      |                                   ^~~~~~~~~~~~~~~~~~~~
+
+Fixes:
+ - http://autobuild.buildroot.org/results/0e04bcdb591ca5642053e1f7e31384f06581e989
+
+Signed-off-by: Fabrice Fontaine <fontaine.fabrice@gmail.com>
+Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
+---
+ Create.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/Create.c
++++ b/Create.c
+@@ -32,6 +32,10 @@
+ #include	<sys/signalfd.h>
+ #include	<sys/wait.h>
+ 
++#ifndef FALLOC_FL_ZERO_RANGE
++#define FALLOC_FL_ZERO_RANGE 16
++#endif
++
+ static int round_size_and_verify(unsigned long long *size, int chunk)
+ {
+ 	if (*size == 0)
diff --git a/package/utils/mdadm/patches/020-basename.patch b/package/utils/mdadm/patches/020-basename.patch
new file mode 100644
index 0000000..d4f7aa5
--- /dev/null
+++ b/package/utils/mdadm/patches/020-basename.patch
@@ -0,0 +1,30 @@
+--- a/Monitor.c
++++ b/Monitor.c
+@@ -27,6 +27,7 @@
+ #include	"md_p.h"
+ #include	"md_u.h"
+ #include	<sys/wait.h>
++#include	<libgen.h>
+ #include	<limits.h>
+ #include	<syslog.h>
+ 
+--- a/platform-intel.c
++++ b/platform-intel.c
+@@ -28,6 +28,7 @@
+ #include <sys/mman.h>
+ #include <sys/types.h>
+ #include <sys/stat.h>
++#include <libgen.h>
+ #include <limits.h>
+ 
+ #define NVME_SUBSYS_PATH "/sys/devices/virtual/nvme-subsystem/"
+--- a/super-intel.c
++++ b/super-intel.c
+@@ -27,6 +27,7 @@
+ #include <scsi/sg.h>
+ #include <ctype.h>
+ #include <dirent.h>
++#include <libgen.h>
+ 
+ /* MPB == Metadata Parameter Block */
+ #define MPB_SIGNATURE "Intel Raid ISM Cfg Sig. "
diff --git a/package/utils/mdadm/patches/030-fix-monitor-tv_sec.patch b/package/utils/mdadm/patches/030-fix-monitor-tv_sec.patch
new file mode 100644
index 0000000..a0fe9fd
--- /dev/null
+++ b/package/utils/mdadm/patches/030-fix-monitor-tv_sec.patch
@@ -0,0 +1,14 @@
+--- a/monitor.c
++++ b/monitor.c
+@@ -449,9 +449,9 @@ static int read_and_act(struct active_ar
+ 	}
+ 
+ 	gettimeofday(&tv, NULL);
+-	dprintf("(%d): %ld.%06ld state:%s prev:%s action:%s prev: %s start:%llu\n",
++	dprintf("(%d): %lld.%06ld state:%s prev:%s action:%s prev: %s start:%llu\n",
+ 		a->info.container_member,
+-		tv.tv_sec, tv.tv_usec,
++		(long long)tv.tv_sec, (long)tv.tv_usec,
+ 		array_states[a->curr_state],
+ 		array_states[a->prev_state],
+ 		sync_actions[a->curr_action],
diff --git a/package/utils/mdadm/patches/040-udev.patch b/package/utils/mdadm/patches/040-udev.patch
new file mode 100644
index 0000000..0d497aa
--- /dev/null
+++ b/package/utils/mdadm/patches/040-udev.patch
@@ -0,0 +1,26 @@
+From 1750758c7ff526e3560433f6235e5cfa35cf646a Mon Sep 17 00:00:00 2001
+From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
+Date: Wed, 6 Mar 2024 15:50:55 +0100
+Subject: udev.c: Do not require libudev.h if DNO_LIBUDEV
+
+libudev may not be presented at all, do not require it.
+
+Reported-by: Boian Bonev <bbonev@ipacct.com>
+Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
+---
+ udev.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/udev.c
++++ b/udev.c
+@@ -26,7 +26,10 @@
+ #include	<signal.h>
+ #include	<limits.h>
+ #include	<syslog.h>
++
++#ifndef NO_LIBUDEV
+ #include	<libudev.h>
++#endif
+ 
+ static char *unblock_path;
+ 
diff --git a/package/utils/mdadm/patches/050-pie.patch b/package/utils/mdadm/patches/050-pie.patch
new file mode 100644
index 0000000..59c96f5
--- /dev/null
+++ b/package/utils/mdadm/patches/050-pie.patch
@@ -0,0 +1,33 @@
+From 893a55831e5abbcd15b171db66fa1f389fb61506 Mon Sep 17 00:00:00 2001
+From: Fabrice Fontaine <fontaine.fabrice@gmail.com>
+Date: Tue, 7 May 2024 19:32:16 +0200
+Subject: Makefile: Move -pie to LDFLAGS
+
+Move -pie from LDLIBS to LDFLAGS and make LDFLAGS configurable to allow
+the user to drop it by setting their own LDFLAGS (e.g. PIE could be
+enabled or disabled by the buildsystem such as buildroot).
+
+Suggested-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
+Signed-off-by: Fabrice Fontaine <fontaine.fabrice@gmail.com>
+Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
+---
+ Makefile | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/Makefile
++++ b/Makefile
+@@ -132,12 +132,12 @@ CFLAGS += -DUSE_PTHREADS
+ MON_LDFLAGS += -pthread
+ endif
+ 
+-LDFLAGS = -Wl,-z,now,-z,noexecstack
++LDFLAGS ?= -pie -Wl,-z,now,-z,noexecstack
+ 
+ # If you want a static binary, you might uncomment these
+ # LDFLAGS += -static
+ # STRIP = -s
+-LDLIBS = -ldl -pie
++LDLIBS = -ldl
+ 
+ # To explicitly disable libudev, set -DNO_LIBUDEV in CXFLAGS
+ ifeq (, $(findstring -DNO_LIBUDEV,  $(CXFLAGS)))
diff --git a/package/utils/mdadm/patches/060-gcc14.patch b/package/utils/mdadm/patches/060-gcc14.patch
new file mode 100644
index 0000000..545a40a
--- /dev/null
+++ b/package/utils/mdadm/patches/060-gcc14.patch
@@ -0,0 +1,24 @@
+From 8bda86099089b44129ef6206764f9de47a45f0db Mon Sep 17 00:00:00 2001
+From: Alexander Kanavin <alex@linutronix.de>
+Date: Tue, 12 Mar 2024 11:01:50 +0100
+Subject: [PATCH] util.c: add limits.h include for NAME_MAX definition
+
+Add limits.h include for NAME_MAX definition.
+
+Signed-off-by: Alexander Kanavin <alex@linutronix.de>
+Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
+---
+ util.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/util.c
++++ b/util.c
+@@ -36,7 +36,7 @@
+ #include	<ctype.h>
+ #include	<dirent.h>
+ #include	<dlfcn.h>
+-
++#include	<limits.h>
+ 
+ /*
+  * following taken from linux/blkpg.h because they aren't
diff --git a/package/utils/mdadm/patches/100-cross_compile.patch b/package/utils/mdadm/patches/100-cross_compile.patch
new file mode 100644
index 0000000..bd71c08
--- /dev/null
+++ b/package/utils/mdadm/patches/100-cross_compile.patch
@@ -0,0 +1,11 @@
+--- a/Makefile
++++ b/Makefile
+@@ -115,7 +115,7 @@ DLM:=$(shell [ -f /usr/include/libdlm.h
+ DIRFLAGS = -DMAP_DIR=\"$(MAP_DIR)\" -DMAP_FILE=\"$(MAP_FILE)\"
+ DIRFLAGS += -DMDMON_DIR=\"$(MDMON_DIR)\"
+ DIRFLAGS += -DFAILED_SLOTS_DIR=\"$(FAILED_SLOTS_DIR)\"
+-CFLAGS = $(CWFLAGS) $(CXFLAGS) -DSendmail=\""$(MAILCMD)"\" $(CONFFILEFLAGS) $(DIRFLAGS) $(COROSYNC) $(DLM)
++#CFLAGS = $(CWFLAGS) $(CXFLAGS) -DSendmail=\""$(MAILCMD)"\" $(CONFFILEFLAGS) $(DIRFLAGS) $(COROSYNC) $(DLM)
+ 
+ VERSION = $(shell [ -d .git ] && git describe HEAD | sed 's/mdadm-//')
+ VERS_DATE = $(shell [ -d .git ] && date --iso-8601 --date="`git log -n1 --format=format:%cd --date=iso --date=short`")
diff --git a/package/utils/mdadm/patches/200-reduce_size.patch b/package/utils/mdadm/patches/200-reduce_size.patch
new file mode 100644
index 0000000..d14fae7
--- /dev/null
+++ b/package/utils/mdadm/patches/200-reduce_size.patch
@@ -0,0 +1,25 @@
+--- a/Incremental.c
++++ b/Incremental.c
+@@ -985,6 +985,10 @@ static int array_try_spare(char *devname
+ 				goto next;
+ 		}
+ 
++		#ifndef MDADM_FULL
++			return 0;
++		#endif
++
+ 		dl = domain_from_array(sra, st2->ss->name);
+ 		if (domain_test(dl, pol, st2->ss->name) != 1) {
+ 			/* domain test fails */
+--- a/util.c
++++ b/util.c
+@@ -1192,7 +1192,9 @@ void wait_for(char *dev, int fd)
+ struct superswitch *superlist[] =
+ {
+ 	&super0, &super1,
++#ifdef MDADM_FULL
+ 	&super_ddf, &super_imsm,
++#endif
+ 	&mbr, &gpt,
+ 	NULL
+ };
diff --git a/package/utils/mtd-utils/Makefile b/package/utils/mtd-utils/Makefile
new file mode 100644
index 0000000..046572e
--- /dev/null
+++ b/package/utils/mtd-utils/Makefile
@@ -0,0 +1,84 @@
+#
+# Copyright (C) 2009-2014 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=mtd-utils
+PKG_VERSION:=2.2.1
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=https://infraroot.at/pub/mtd/
+PKG_HASH:=f7ae20b2eb79ee83441468f0b99d897024cd96ff853eea59106fb1952065c803
+
+PKG_INSTALL:=1
+
+PKG_FLAGS:=nonshared
+PKG_BUILD_FLAGS:=gc-sections
+
+PKG_BUILD_DEPENDS:=util-linux
+
+PKG_LICENSE:=GPLv2
+PKG_LICENSE_FILES:=
+PKG_CPE_ID:=cpe:/a:mtd-utils_project:mtd-utils
+
+PKG_MAINTAINER:=John Crispin <john@phrozen.org>
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/mtd-utils/Default
+  SECTION:=utils
+  CATEGORY:=Utilities
+  URL:=http://www.linux-mtd.infradead.org/
+  DEPENDS:=@NAND_SUPPORT
+endef
+
+define Package/ubi-utils
+ $(call Package/mtd-utils/Default)
+  TITLE:=Utilities for ubi info/debug
+endef
+
+define Package/ubi-utils/description
+  Utilities for manipulating memory technology devices.
+endef
+
+define Package/nand-utils
+ $(call Package/mtd-utils/Default)
+  TITLE:=Utilities for nand flash erase/read/write/test
+endef
+
+define Package/nand-utils/description
+  Utilities for NAND devices.
+endef
+
+MAKE_FLAGS += LDLIBS+="$(LIBGCC_S)"
+
+CONFIGURE_ARGS += \
+	--enable-tests \
+	--without-crypto \
+	--without-xattr \
+	--without-zstd \
+	--without-lzo \
+	--without-zlib
+
+define Package/ubi-utils/install
+	$(INSTALL_DIR) $(1)/usr/sbin
+	$(INSTALL_BIN) \
+		$(PKG_INSTALL_DIR)/usr/sbin/{ubiattach,ubicrc32,ubiblock,ubidetach,ubiformat,ubimkvol} $(1)/usr/sbin/
+	$(INSTALL_BIN) \
+		$(PKG_INSTALL_DIR)/usr/sbin/{ubinfo,ubinize,ubirename,ubirmvol,ubirsvol,ubiupdatevol} $(1)/usr/sbin/
+endef
+
+define Package/nand-utils/install
+	$(INSTALL_DIR) $(1)/usr/sbin
+	$(INSTALL_BIN) \
+	$(PKG_INSTALL_DIR)/usr/sbin/{flash_erase,nanddump,nandwrite,nandtest,mtdinfo} \
+	$(PKG_INSTALL_DIR)/usr/lib/mtd-utils/nandbiterrs $(1)/usr/sbin/
+endef
+
+$(eval $(call BuildPackage,ubi-utils))
+$(eval $(call BuildPackage,nand-utils))
diff --git a/package/utils/nvram/Makefile b/package/utils/nvram/Makefile
new file mode 100644
index 0000000..8547bfa
--- /dev/null
+++ b/package/utils/nvram/Makefile
@@ -0,0 +1,55 @@
+#
+# Copyright (C) 2009-2010 Jo-Philipp Wich <xm@subsignal.org>
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=nvram
+PKG_RELEASE:=12
+
+PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
+
+PKG_FLAGS:=nonshared
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/nvram
+  SECTION:=utils
+  CATEGORY:=Base system
+  TITLE:=Userspace port of the Broadcom NVRAM manipulation tool
+  MAINTAINER:=Jo-Philipp Wich <xm@subsignal.org>
+  DEPENDS:=@(TARGET_bcm47xx||TARGET_bcm53xx||TARGET_ath79)
+endef
+
+define Package/nvram/description
+ This package contains an utility to manipulate NVRAM on Broadcom based devices.
+ It works on bcm47xx (Linux 2.6) without using the kernel api.
+endef
+
+define Build/Configure
+endef
+
+define Build/Compile
+	$(MAKE) -C $(PKG_BUILD_DIR) \
+		CC="$(TARGET_CC)" \
+		CFLAGS="$(TARGET_CFLAGS) -Wall" \
+		LDFLAGS="$(TARGET_LDFLAGS)"
+endef
+
+define Package/nvram/install
+	$(INSTALL_DIR) $(1)/usr/sbin
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/nvram $(1)/usr/sbin/
+ifneq ($(CONFIG_TARGET_bcm47xx),)
+	$(INSTALL_DIR) $(1)/etc/init.d
+	$(INSTALL_BIN) ./files/nvram-bcm47xx.init $(1)/etc/init.d/nvram
+endif
+ifneq ($(CONFIG_TARGET_bcm53xx),)
+	$(INSTALL_DIR) $(1)/etc/init.d
+	$(INSTALL_BIN) ./files/nvram-bcm53xx.init $(1)/etc/init.d/nvram
+endif
+endef
+
+$(eval $(call BuildPackage,nvram))
diff --git a/package/utils/nvram/files/nvram-bcm47xx.init b/package/utils/nvram/files/nvram-bcm47xx.init
new file mode 100755
index 0000000..4a2bcd1
--- /dev/null
+++ b/package/utils/nvram/files/nvram-bcm47xx.init
@@ -0,0 +1,98 @@
+#!/bin/sh /etc/rc.common
+# NVRAM setup
+#
+# This file handles the NVRAM quirks of various hardware of the bcm47xx target.
+
+START=02
+alias debug=${DEBUG:-:}
+
+nvram_default() {
+	[ -z "$(nvram get $1)" ] && nvram set "$1=$2"
+}
+
+nvram_set() { # for the linksys fixup part
+	[ "$(nvram get "$1")" = "$2" -a "$2" != "" ] || {
+		COMMIT=1
+		/usr/sbin/nvram set "$1=$2"
+	}
+}
+
+fixup_linksys() {
+	# work around braindead CFE defaults in linksys routers
+	boardtype=$(nvram get boardtype)
+	boardnum=$(nvram get boardnum)
+	boardflags=$(($(nvram get boardflags)))
+	adm_switch="$(( ($boardflags & 0x80) >> 7 ))"
+
+	[ -n "$(nvram get vxkilled)" ] && boardtype=0 # don't mess with the ram settings on the hacked cfe
+	case "$(( $boardtype ))" in
+		"1800") #0x708
+			if [ "$adm_switch" = 0 ]; then
+				nvram_set sdram_init "$(printf 0x%04x $(( $(/usr/sbin/nvram get sdram_init) | 0x0100 )))"
+				[ "$COMMIT" = 1 ] && {
+					nvram_set clkfreq 216
+					nvram_set sdram_ncdl 0x0
+					nvram_set pa0itssit 62
+					nvram_set pa0b0 0x15eb
+					nvram_set pa0b1 0xfa82
+					nvram_set pa0b2 0xfe66
+					nvram_set pa0maxpwr 0x4e
+				}
+			fi
+		;;
+		"1127") #0x467
+			nvram_set sdram_init "$(printf 0x%04x $(( $(/usr/sbin/nvram get sdram_init) | 0x0100 )))"
+			[ "$COMMIT" = 1 ] && {
+				nvram_set sdram_ncdl 0x0
+				nvram_set pa0itssit 62
+				nvram_set pa0b0 0x168b
+				nvram_set pa0b1 0xfabf
+				nvram_set pa0b2 0xfeaf
+				nvram_set pa0maxpwr 0x4e
+			}
+		;;
+		"1071") #0x042f
+			# do sanity check first! max 0x0011 = 128mb
+			SDRAM_INIT=$(printf %d $(/usr/sbin/nvram get sdram_init))
+			[ "$SDRAM_INIT" -lt "9" -o "$SDRAM_INIT" -gt "17" ] && {
+				# set this to default: 0x09 only if value is invaild like 16MB on Asus WL-500GP
+				echo "sdram_init is invaild: $(printf 0x%04x $SDRAM_INIT), force to default!"
+				nvram_set sdram_init 0x0009
+			}
+			# on WRT54G3GV2 set flag, so checksum errors of firmware image 2 don't stop the boot process
+			noset_try_flag=$(nvram get noset_try_flag)
+			[ "$noset_try_flag" = 0 ] && {
+				echo "setting noset_try_flag to 1."
+				nvram_set noset_try_flag 1
+			}
+			[ "$COMMIT" = 1 ] && {
+				nvram_set sdram_ncdl 0x0
+			}
+	esac
+}
+
+boot() {
+	# Don't do any fixups on the WGT634U
+	[ "$(cat /proc/diag/model)" = "Netgear WGT634U" ] && return
+
+	fixup_linksys
+
+	# OFDM Power Offset is set incorrectly on many boards.
+	# Setting it to 0 will increase the tx power to normal levels.
+	nvram_set opo 0x0
+
+	[ "$(nvram get il0macaddr)" = "00:90:4c:5f:00:2a" ] && {
+		# if default wifi mac, set two higher than the lan mac
+		nvram set il0macaddr=$(nvram get et0macaddr|
+		awk '{OFS=FS=":";for(x=7,y=2;--x;){$x=sprintf("%02x",(y+="0x"$x)%256);y/=256}print}')
+	}
+
+	[ "$(nvram get et0macaddr)" = "00:90:4c:c0:00:08" ] && {
+		# OvisLink WL-1600GL mac workaround
+		nvram set et0macaddr=$(hexdump -n 6 -s 130976 -e '5/1 "%02x:" "%02x" ' /dev/mtd/0)
+		nvram set il0macaddr=$(nvram get et0macaddr|
+		awk '{OFS=FS=":";for(x=7,y=2;--x;){$x=sprintf("%02x",(y+="0x"$x)%256);y/=256}print}')
+	}
+
+	[ "$COMMIT" = "1" ] && nvram commit
+}
diff --git a/package/utils/nvram/files/nvram-bcm53xx.init b/package/utils/nvram/files/nvram-bcm53xx.init
new file mode 100755
index 0000000..f47c944
--- /dev/null
+++ b/package/utils/nvram/files/nvram-bcm53xx.init
@@ -0,0 +1,42 @@
+#!/bin/sh /etc/rc.common
+# NVRAM setup
+#
+# This file handles the NVRAM quirks of various hardware of the bcm53xx target.
+
+START=02
+
+clear_partialboots() {
+	# clear partialboots
+
+	case $(board_name) in
+		linksys,ea9200|\
+		linksys,panamera)
+			COMMIT=1
+			nvram set partialboots=0
+			;;
+	esac
+}
+
+set_wireless_led_behaviour() {
+	# set Broadcom wireless LED behaviour for both radios
+	# 0:ledbh9 -> Behaviour of 2.4GHz LED
+	# 1:ledbh9 -> Behaviour of 5GHz LED
+	# 0x7 makes the wireless LEDs on, when radios are enabled, and blink when there's activity
+
+	case $(board_name) in
+		asus,rt-ac3100|\
+		asus,rt-ac88u)
+			COMMIT=1
+			nvram set 0:ledbh9=0x7 set 1:ledbh9=0x7
+			;;
+	esac
+}
+
+boot() {
+	. /lib/functions.sh
+
+	clear_partialboots
+	set_wireless_led_behaviour
+
+	[ "$COMMIT" = "1" ] && nvram commit
+}
diff --git a/package/utils/nvram/src/Makefile b/package/utils/nvram/src/Makefile
new file mode 100644
index 0000000..68a6354
--- /dev/null
+++ b/package/utils/nvram/src/Makefile
@@ -0,0 +1,7 @@
+all: nvram
+
+nvram:
+	$(CC) $(CFLAGS) -o $@ cli.c crc.c nvram.c $(LDFLAGS)
+
+clean:
+	rm -f nvram
diff --git a/package/utils/nvram/src/cli.c b/package/utils/nvram/src/cli.c
new file mode 100644
index 0000000..224a2b7
--- /dev/null
+++ b/package/utils/nvram/src/cli.c
@@ -0,0 +1,255 @@
+/*
+ * Command line interface for libnvram
+ *
+ * Copyright 2009, Jo-Philipp Wich <xm@subsignal.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ * The libnvram code is based on Broadcom code for Linux 2.4.x .
+ *
+ */
+
+#include "nvram.h"
+
+
+static nvram_handle_t * nvram_open_rdonly(void)
+{
+	char *file = nvram_find_staging();
+
+	if( file == NULL )
+		file = nvram_find_mtd();
+
+	if( file != NULL ) {
+		nvram_handle_t *h = nvram_open(file, NVRAM_RO);
+		if( strcmp(file, NVRAM_STAGING) )
+			free(file);
+		return h;
+	}
+
+	return NULL;
+}
+
+static nvram_handle_t * nvram_open_staging(void)
+{
+	if( nvram_find_staging() != NULL || nvram_to_staging() == 0 )
+		return nvram_open(NVRAM_STAGING, NVRAM_RW);
+
+	return NULL;
+}
+
+static int do_show(nvram_handle_t *nvram)
+{
+	nvram_tuple_t *t;
+	int stat = 1;
+
+	if( (t = nvram_getall(nvram)) != NULL )
+	{
+		while( t )
+		{
+			printf("%s=%s\n", t->name, t->value);
+			t = t->next;
+		}
+
+		stat = 0;
+	}
+
+	return stat;
+}
+
+static int do_get(nvram_handle_t *nvram, const char *var)
+{
+	const char *val;
+	int stat = 1;
+
+	if( (val = nvram_get(nvram, var)) != NULL )
+	{
+		printf("%s\n", val);
+		stat = 0;
+	}
+
+	return stat;
+}
+
+static int do_unset(nvram_handle_t *nvram, const char *var)
+{
+	return nvram_unset(nvram, var);
+}
+
+static int do_set(nvram_handle_t *nvram, const char *pair)
+{
+	char *val = strstr(pair, "=");
+	char var[strlen(pair)];
+	int stat = 1;
+
+	if( val != NULL )
+	{
+		memset(var, 0, sizeof(var));
+		strncpy(var, pair, (int)(val-pair));
+		stat = nvram_set(nvram, var, (char *)(val + 1));
+	}
+
+	return stat;
+}
+
+static int do_info(nvram_handle_t *nvram)
+{
+	nvram_header_t *hdr = nvram_header(nvram);
+
+	/* CRC8 over the last 11 bytes of the header and data bytes */
+	uint8_t crc = hndcrc8((unsigned char *) &hdr[0] + NVRAM_CRC_START_POSITION,
+		hdr->len - NVRAM_CRC_START_POSITION, 0xff);
+
+	/* Show info */
+	printf("Magic:         0x%08X\n",   hdr->magic);
+	printf("Length:        0x%08X\n",   hdr->len);
+	printf("Offset:        0x%08X\n",   nvram->offset);
+
+	printf("CRC8:          0x%02X (calculated: 0x%02X)\n",
+		hdr->crc_ver_init & 0xFF, crc);
+
+	printf("Version:       0x%02X\n",   (hdr->crc_ver_init >> 8) & 0xFF);
+	printf("SDRAM init:    0x%04X\n",   (hdr->crc_ver_init >> 16) & 0xFFFF);
+	printf("SDRAM config:  0x%04X\n",   hdr->config_refresh & 0xFFFF);
+	printf("SDRAM refresh: 0x%04X\n",   (hdr->config_refresh >> 16) & 0xFFFF);
+	printf("NCDL values:   0x%08X\n\n", hdr->config_ncdl);
+
+	printf("%i bytes used / %i bytes available (%.2f%%)\n",
+		hdr->len, nvram->length - nvram->offset - hdr->len,
+		(100.00 / (double)(nvram->length - nvram->offset)) * (double)hdr->len);
+
+	return 0;
+}
+
+static void usage(void)
+{
+	fprintf(stderr,
+		"Usage:\n"
+		"	nvram show\n"
+		"	nvram info\n"
+		"	nvram get variable\n"
+		"	nvram set variable=value [set ...]\n"
+		"	nvram unset variable [unset ...]\n"
+		"	nvram commit\n"
+	);
+}
+
+int main( int argc, const char *argv[] )
+{
+	nvram_handle_t *nvram;
+	int commit = 0;
+	int write = 0;
+	int stat = 1;
+	int done = 0;
+	int i;
+
+	if( argc < 2 ) {
+		usage();
+		return 1;
+	}
+
+	/* Ugly... iterate over arguments to see whether we can expect a write */
+	if( ( !strcmp(argv[1], "set")  && 2 < argc ) ||
+		( !strcmp(argv[1], "unset") && 2 < argc ) ||
+		!strcmp(argv[1], "commit") )
+		write = 1;
+
+
+	nvram = write ? nvram_open_staging() : nvram_open_rdonly();
+
+	if( nvram != NULL && argc > 1 )
+	{
+		for( i = 1; i < argc; i++ )
+		{
+			if( !strcmp(argv[i], "show") )
+			{
+				stat = do_show(nvram);
+				done++;
+			}
+			else if( !strcmp(argv[i], "info") )
+			{
+				stat = do_info(nvram);
+				done++;
+			}
+			else if( !strcmp(argv[i], "get") || !strcmp(argv[i], "unset") || !strcmp(argv[i], "set") )
+			{
+				if( (i+1) < argc )
+				{
+					switch(argv[i++][0])
+					{
+						case 'g':
+							stat = do_get(nvram, argv[i]);
+							break;
+
+						case 'u':
+							stat = do_unset(nvram, argv[i]);
+							break;
+
+						case 's':
+							stat = do_set(nvram, argv[i]);
+							break;
+					}
+					done++;
+				}
+				else
+				{
+					fprintf(stderr, "Command '%s' requires an argument!\n", argv[i]);
+					done = 0;
+					break;
+				}
+			}
+			else if( !strcmp(argv[i], "commit") )
+			{
+				commit = 1;
+				done++;
+			}
+			else
+			{
+				fprintf(stderr, "Unknown option '%s' !\n", argv[i]);
+				done = 0;
+				break;
+			}
+		}
+
+		if( write )
+			stat = nvram_commit(nvram);
+
+		nvram_close(nvram);
+
+		if( commit )
+			stat = staging_to_nvram();
+	}
+
+	if( !nvram )
+	{
+		fprintf(stderr,
+			"Could not open nvram! Possible reasons are:\n"
+			"	- No device found (/proc not mounted or no nvram present)\n"
+			"	- Insufficient permissions to open mtd device\n"
+			"	- Insufficient memory to complete operation\n"
+			"	- Memory mapping failed or not supported\n"
+			"	- Nvram magic not found in specific nvram partition\n"
+		);
+
+		stat = 1;
+	}
+	else if( !done )
+	{
+		usage();
+		stat = 1;
+	}
+
+	return stat;
+}
diff --git a/package/utils/nvram/src/crc.c b/package/utils/nvram/src/crc.c
new file mode 100644
index 0000000..22a3665
--- /dev/null
+++ b/package/utils/nvram/src/crc.c
@@ -0,0 +1,69 @@
+#include "nvram.h"
+
+/*******************************************************************************
+ * crc8
+ *
+ * Computes a crc8 over the input data using the polynomial:
+ *
+ *       x^8 + x^7 +x^6 + x^4 + x^2 + 1
+ *
+ * The caller provides the initial value (either CRC8_INIT_VALUE
+ * or the previous returned value) to allow for processing of
+ * discontiguous blocks of data.  When generating the CRC the
+ * caller is responsible for complementing the final return value
+ * and inserting it into the byte stream.  When checking, a final
+ * return value of CRC8_GOOD_VALUE indicates a valid CRC.
+ *
+ * Reference: Dallas Semiconductor Application Note 27
+ *   Williams, Ross N., "A Painless Guide to CRC Error Detection Algorithms",
+ *     ver 3, Aug 1993, ross@guest.adelaide.edu.au, Rocksoft Pty Ltd.,
+ *     ftp://ftp.rocksoft.com/clients/rocksoft/papers/crc_v3.txt
+ *
+ * ****************************************************************************
+ */
+
+static const uint8_t crc8_table[256] = {
+	0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B,
+	0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21,
+	0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF,
+	0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5,
+	0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14,
+	0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E,
+	0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80,
+	0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA,
+	0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95,
+	0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF,
+	0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01,
+	0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B,
+	0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA,
+	0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0,
+	0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E,
+	0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34,
+	0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0,
+	0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A,
+	0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54,
+	0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E,
+	0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF,
+	0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5,
+	0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B,
+	0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61,
+	0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E,
+	0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74,
+	0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA,
+	0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0,
+	0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41,
+	0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B,
+	0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5,
+	0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F
+};
+
+uint8_t hndcrc8 (
+	uint8_t * pdata,  /* pointer to array of data to process */
+	uint32_t nbytes,  /* number of input data bytes to process */
+	uint8_t crc       /* either CRC8_INIT_VALUE or previous return value */
+) {
+	while (nbytes-- > 0)
+		crc = crc8_table[(crc ^ *pdata++) & 0xff];
+
+	return crc;
+}
diff --git a/package/utils/nvram/src/nvram.c b/package/utils/nvram/src/nvram.c
new file mode 100644
index 0000000..d5e12ee
--- /dev/null
+++ b/package/utils/nvram/src/nvram.c
@@ -0,0 +1,547 @@
+/*
+ * NVRAM variable manipulation (common)
+ *
+ * Copyright 2004, Broadcom Corporation
+ * Copyright 2009-2010, OpenWrt.org
+ * All Rights Reserved.
+ *
+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
+ *
+ */
+
+#include "nvram.h"
+
+#define TRACE(msg) \
+	printf("%s(%i) in %s(): %s\n", \
+		__FILE__, __LINE__, __FUNCTION__, msg ? msg : "?")
+
+/* Size of "nvram" MTD partition */
+size_t nvram_part_size = 0;
+
+
+/*
+ * -- Helper functions --
+ */
+
+/* String hash */
+static uint32_t hash(const char *s)
+{
+	uint32_t hash = 0;
+
+	while (*s)
+		hash = 31 * hash + *s++;
+
+	return hash;
+}
+
+/* Free all tuples. */
+static void _nvram_free(nvram_handle_t *h)
+{
+	uint32_t i;
+	nvram_tuple_t *t, *next;
+
+	/* Free hash table */
+	for (i = 0; i < NVRAM_ARRAYSIZE(h->nvram_hash); i++) {
+		for (t = h->nvram_hash[i]; t; t = next) {
+			next = t->next;
+			if (t->value)
+				free(t->value);
+			free(t);
+		}
+		h->nvram_hash[i] = NULL;
+	}
+
+	/* Free dead table */
+	for (t = h->nvram_dead; t; t = next) {
+		next = t->next;
+		if (t->value)
+			free(t->value);
+		free(t);
+	}
+
+	h->nvram_dead = NULL;
+}
+
+/* (Re)allocate NVRAM tuples. */
+static nvram_tuple_t * _nvram_realloc( nvram_handle_t *h, nvram_tuple_t *t,
+	const char *name, const char *value )
+{
+	if ((strlen(value) + 1) > h->length - h->offset)
+		return NULL;
+
+	if (!t) {
+		if (!(t = malloc(sizeof(nvram_tuple_t) + strlen(name) + 1)))
+			return NULL;
+
+		/* Copy name */
+		t->name = (char *) &t[1];
+		strcpy(t->name, name);
+
+		t->value = NULL;
+	}
+
+	/* Copy value */
+	if (!t->value || strcmp(t->value, value))
+	{
+		if(!(t->value = (char *) realloc(t->value, strlen(value)+1)))
+			return NULL;
+
+		strcpy(t->value, value);
+		t->value[strlen(value)] = '\0';
+	}
+
+	return t;
+}
+
+/* (Re)initialize the hash table. */
+static int _nvram_rehash(nvram_handle_t *h)
+{
+	nvram_header_t *header = nvram_header(h);
+	char buf[] = "0xXXXXXXXX", *name, *value, *eq;
+
+	/* (Re)initialize hash table */
+	_nvram_free(h);
+
+	/* Parse and set "name=value\0 ... \0\0" */
+	name = (char *) &header[1];
+
+	for (; *name; name = value + strlen(value) + 1) {
+		if (!(eq = strchr(name, '=')))
+			break;
+		*eq = '\0';
+		value = eq + 1;
+		nvram_set(h, name, value);
+		*eq = '=';
+	}
+
+	/* Set special SDRAM parameters */
+	if (!nvram_get(h, "sdram_init")) {
+		sprintf(buf, "0x%04X", (uint16_t)(header->crc_ver_init >> 16));
+		nvram_set(h, "sdram_init", buf);
+	}
+	if (!nvram_get(h, "sdram_config")) {
+		sprintf(buf, "0x%04X", (uint16_t)(header->config_refresh & 0xffff));
+		nvram_set(h, "sdram_config", buf);
+	}
+	if (!nvram_get(h, "sdram_refresh")) {
+		sprintf(buf, "0x%04X",
+			(uint16_t)((header->config_refresh >> 16) & 0xffff));
+		nvram_set(h, "sdram_refresh", buf);
+	}
+	if (!nvram_get(h, "sdram_ncdl")) {
+		sprintf(buf, "0x%08X", header->config_ncdl);
+		nvram_set(h, "sdram_ncdl", buf);
+	}
+
+	return 0;
+}
+
+
+/*
+ * -- Public functions --
+ */
+
+/* Get nvram header. */
+nvram_header_t * nvram_header(nvram_handle_t *h)
+{
+	return (nvram_header_t *) &h->mmap[h->offset];
+}
+
+/* Get the value of an NVRAM variable. */
+char * nvram_get(nvram_handle_t *h, const char *name)
+{
+	uint32_t i;
+	nvram_tuple_t *t;
+	char *value;
+
+	if (!name)
+		return NULL;
+
+	/* Hash the name */
+	i = hash(name) % NVRAM_ARRAYSIZE(h->nvram_hash);
+
+	/* Find the associated tuple in the hash table */
+	for (t = h->nvram_hash[i]; t && strcmp(t->name, name); t = t->next);
+
+	value = t ? t->value : NULL;
+
+	return value;
+}
+
+/* Set the value of an NVRAM variable. */
+int nvram_set(nvram_handle_t *h, const char *name, const char *value)
+{
+	uint32_t i;
+	nvram_tuple_t *t, *u, **prev;
+
+	/* Hash the name */
+	i = hash(name) % NVRAM_ARRAYSIZE(h->nvram_hash);
+
+	/* Find the associated tuple in the hash table */
+	for (prev = &h->nvram_hash[i], t = *prev;
+		 t && strcmp(t->name, name); prev = &t->next, t = *prev);
+
+	/* (Re)allocate tuple */
+	if (!(u = _nvram_realloc(h, t, name, value)))
+		return -12; /* -ENOMEM */
+
+	/* Value reallocated */
+	if (t && t == u)
+		return 0;
+
+	/* Move old tuple to the dead table */
+	if (t) {
+		*prev = t->next;
+		t->next = h->nvram_dead;
+		h->nvram_dead = t;
+	}
+
+	/* Add new tuple to the hash table */
+	u->next = h->nvram_hash[i];
+	h->nvram_hash[i] = u;
+
+	return 0;
+}
+
+/* Unset the value of an NVRAM variable. */
+int nvram_unset(nvram_handle_t *h, const char *name)
+{
+	uint32_t i;
+	nvram_tuple_t *t, **prev;
+
+	if (!name)
+		return 0;
+
+	/* Hash the name */
+	i = hash(name) % NVRAM_ARRAYSIZE(h->nvram_hash);
+
+	/* Find the associated tuple in the hash table */
+	for (prev = &h->nvram_hash[i], t = *prev;
+		 t && strcmp(t->name, name); prev = &t->next, t = *prev);
+
+	/* Move it to the dead table */
+	if (t) {
+		*prev = t->next;
+		t->next = h->nvram_dead;
+		h->nvram_dead = t;
+	}
+
+	return 0;
+}
+
+/* Get all NVRAM variables. */
+nvram_tuple_t * nvram_getall(nvram_handle_t *h)
+{
+	int i;
+	nvram_tuple_t *t, *l, *x;
+
+	l = NULL;
+
+	for (i = 0; i < NVRAM_ARRAYSIZE(h->nvram_hash); i++) {
+		for (t = h->nvram_hash[i]; t; t = t->next) {
+			if( (x = (nvram_tuple_t *) malloc(sizeof(nvram_tuple_t))) != NULL )
+			{
+				x->name  = t->name;
+				x->value = t->value;
+				x->next  = l;
+				l = x;
+			}
+			else
+			{
+				break;
+			}
+		}
+	}
+
+	return l;
+}
+
+/* Regenerate NVRAM. */
+int nvram_commit(nvram_handle_t *h)
+{
+	nvram_header_t *header = nvram_header(h);
+	char *init, *config, *refresh, *ncdl;
+	char *ptr, *end;
+	int i;
+	nvram_tuple_t *t;
+	nvram_header_t tmp;
+	uint8_t crc;
+
+	/* Regenerate header */
+	header->magic = NVRAM_MAGIC;
+	header->crc_ver_init = (NVRAM_VERSION << 8);
+	if (!(init = nvram_get(h, "sdram_init")) ||
+		!(config = nvram_get(h, "sdram_config")) ||
+		!(refresh = nvram_get(h, "sdram_refresh")) ||
+		!(ncdl = nvram_get(h, "sdram_ncdl"))) {
+		header->crc_ver_init |= SDRAM_INIT << 16;
+		header->config_refresh = SDRAM_CONFIG;
+		header->config_refresh |= SDRAM_REFRESH << 16;
+		header->config_ncdl = 0;
+	} else {
+		header->crc_ver_init |= (strtoul(init, NULL, 0) & 0xffff) << 16;
+		header->config_refresh = strtoul(config, NULL, 0) & 0xffff;
+		header->config_refresh |= (strtoul(refresh, NULL, 0) & 0xffff) << 16;
+		header->config_ncdl = strtoul(ncdl, NULL, 0);
+	}
+
+	/* Clear data area */
+	ptr = (char *) header + sizeof(nvram_header_t);
+	memset(ptr, 0xFF, nvram_part_size - h->offset - sizeof(nvram_header_t));
+	memset(&tmp, 0, sizeof(nvram_header_t));
+
+	/* Leave space for a double NUL at the end */
+	end = (char *) header + nvram_part_size - h->offset - 2;
+
+	/* Write out all tuples */
+	for (i = 0; i < NVRAM_ARRAYSIZE(h->nvram_hash); i++) {
+		for (t = h->nvram_hash[i]; t; t = t->next) {
+			if ((ptr + strlen(t->name) + 1 + strlen(t->value) + 1) > end)
+				break;
+			ptr += sprintf(ptr, "%s=%s", t->name, t->value) + 1;
+		}
+	}
+
+	/* End with a double NULL and pad to 4 bytes */
+	*ptr = '\0';
+	ptr++;
+
+	if( (int)ptr % 4 )
+		memset(ptr, 0, 4 - ((int)ptr % 4));
+
+	ptr++;
+
+	/* Set new length */
+	header->len = NVRAM_ROUNDUP(ptr - (char *) header, 4);
+
+	/* Little-endian CRC8 over the last 11 bytes of the header */
+	tmp.crc_ver_init   = header->crc_ver_init;
+	tmp.config_refresh = header->config_refresh;
+	tmp.config_ncdl    = header->config_ncdl;
+	crc = hndcrc8((unsigned char *) &tmp + NVRAM_CRC_START_POSITION,
+		sizeof(nvram_header_t) - NVRAM_CRC_START_POSITION, 0xff);
+
+	/* Continue CRC8 over data bytes */
+	crc = hndcrc8((unsigned char *) &header[0] + sizeof(nvram_header_t),
+		header->len - sizeof(nvram_header_t), crc);
+
+	/* Set new CRC8 */
+	header->crc_ver_init |= crc;
+
+	/* Write out */
+	msync(h->mmap, h->length, MS_SYNC);
+	fsync(h->fd);
+
+	/* Reinitialize hash table */
+	return _nvram_rehash(h);
+}
+
+/* Open NVRAM and obtain a handle. */
+nvram_handle_t * nvram_open(const char *file, int rdonly)
+{
+	int i;
+	int fd;
+	char *mtd = NULL;
+	nvram_handle_t *h;
+	nvram_header_t *header;
+	int offset = -1;
+
+	/* If erase size or file are undefined then try to define them */
+	if( (nvram_part_size == 0) || (file == NULL) )
+	{
+		/* Finding the mtd will set the appropriate erase size */
+		if( (mtd = nvram_find_mtd()) == NULL || nvram_part_size == 0 )
+		{
+			free(mtd);
+			return NULL;
+		}
+	}
+
+	if( (fd = open(file ? file : mtd, O_RDWR)) > -1 )
+	{
+		char *mmap_area = (char *) mmap(
+			NULL, nvram_part_size, PROT_READ | PROT_WRITE,
+			(( rdonly == NVRAM_RO ) ? MAP_PRIVATE : MAP_SHARED) | MAP_LOCKED, fd, 0);
+
+		if( mmap_area != MAP_FAILED )
+		{
+			/*
+			 * Start looking for NVRAM_MAGIC at beginning of MTD
+			 * partition. Stop if there is less than NVRAM_MIN_SPACE
+			 * to check, that was the lowest used size.
+			 */
+			for( i = 0; i <= ((nvram_part_size - NVRAM_MIN_SPACE) / sizeof(uint32_t)); i++ )
+			{
+				if( ((uint32_t *)mmap_area)[i] == NVRAM_MAGIC )
+				{
+					offset = i * sizeof(uint32_t);
+					break;
+				}
+			}
+
+			if( offset < 0 )
+			{
+				munmap(mmap_area, nvram_part_size);
+				free(mtd);
+				close(fd);
+				return NULL;
+			}
+			else if( (h = malloc(sizeof(nvram_handle_t))) != NULL )
+			{
+				memset(h, 0, sizeof(nvram_handle_t));
+
+				h->fd     = fd;
+				h->mmap   = mmap_area;
+				h->length = nvram_part_size;
+				h->offset = offset;
+
+				header = nvram_header(h);
+
+				if (header->magic == NVRAM_MAGIC &&
+				    (rdonly || header->len < h->length - h->offset)) {
+					_nvram_rehash(h);
+					free(mtd);
+					return h;
+				}
+				else
+				{
+					munmap(h->mmap, h->length);
+					free(h);
+				}
+			}
+		}
+	}
+
+	free(mtd);
+	close(fd);
+	return NULL;
+}
+
+/* Close NVRAM and free memory. */
+int nvram_close(nvram_handle_t *h)
+{
+	_nvram_free(h);
+	munmap(h->mmap, h->length);
+	close(h->fd);
+	free(h);
+
+	return 0;
+}
+
+/* Determine NVRAM device node. */
+char * nvram_find_mtd(void)
+{
+	FILE *fp;
+	int i, part_size;
+	char dev[PATH_MAX];
+	char *path = NULL;
+	struct stat s;
+
+	if ((fp = fopen("/proc/mtd", "r")))
+	{
+		while( fgets(dev, sizeof(dev), fp) )
+		{
+			if( strstr(dev, "nvram") && sscanf(dev, "mtd%d: %08x", &i, &part_size) )
+			{
+				nvram_part_size = part_size;
+
+				sprintf(dev, "/dev/mtdblock%d", i);
+				if( stat(dev, &s) > -1 && (s.st_mode & S_IFBLK) )
+				{
+					if( (path = (char *) malloc(strlen(dev)+1)) != NULL )
+					{
+						strncpy(path, dev, strlen(dev)+1);
+						break;
+					}
+				}
+			}
+		}
+		fclose(fp);
+	}
+
+	return path;
+}
+
+/* Check NVRAM staging file. */
+char * nvram_find_staging(void)
+{
+	struct stat s;
+
+	if( (stat(NVRAM_STAGING, &s) > -1) && (s.st_mode & S_IFREG) )
+	{
+		return NVRAM_STAGING;
+	}
+
+	return NULL;
+}
+
+/* Copy NVRAM contents to staging file. */
+int nvram_to_staging(void)
+{
+	int fdmtd, fdstg, stat;
+	char *mtd = nvram_find_mtd();
+	char buf[nvram_part_size];
+
+	stat = -1;
+
+	if( (mtd != NULL) && (nvram_part_size > 0) )
+	{
+		if( (fdmtd = open(mtd, O_RDONLY)) > -1 )
+		{
+			if( read(fdmtd, buf, sizeof(buf)) == sizeof(buf) )
+			{
+				if((fdstg = open(NVRAM_STAGING, O_WRONLY | O_CREAT, 0600)) > -1)
+				{
+					write(fdstg, buf, sizeof(buf));
+					fsync(fdstg);
+					close(fdstg);
+
+					stat = 0;
+				}
+			}
+
+			close(fdmtd);
+		}
+	}
+
+	free(mtd);
+	return stat;
+}
+
+/* Copy staging file to NVRAM device. */
+int staging_to_nvram(void)
+{
+	int fdmtd, fdstg, stat;
+	char *mtd = nvram_find_mtd();
+	char buf[nvram_part_size];
+
+	stat = -1;
+
+	if( (mtd != NULL) && (nvram_part_size > 0) )
+	{
+		if( (fdstg = open(NVRAM_STAGING, O_RDONLY)) > -1 )
+		{
+			if( read(fdstg, buf, sizeof(buf)) == sizeof(buf) )
+			{
+				if( (fdmtd = open(mtd, O_WRONLY | O_SYNC)) > -1 )
+				{
+					write(fdmtd, buf, sizeof(buf));
+					fsync(fdmtd);
+					close(fdmtd);
+					stat = 0;
+				}
+			}
+
+			close(fdstg);
+
+			if( !stat )
+				stat = unlink(NVRAM_STAGING) ? 1 : 0;
+		}
+	}
+
+	free(mtd);
+	return stat;
+}
diff --git a/package/utils/nvram/src/nvram.h b/package/utils/nvram/src/nvram.h
new file mode 100644
index 0000000..724f33b
--- /dev/null
+++ b/package/utils/nvram/src/nvram.h
@@ -0,0 +1,123 @@
+/*
+ * NVRAM variable manipulation
+ *
+ * Copyright 2007, Broadcom Corporation
+ * Copyright 2009, OpenWrt.org
+ * All Rights Reserved.
+ *
+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
+ *
+ */
+
+#ifndef _nvram_h_
+#define _nvram_h_
+
+#include <stdint.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <linux/limits.h>
+
+#include "sdinitvals.h"
+
+
+struct nvram_header {
+	uint32_t magic;
+	uint32_t len;
+	uint32_t crc_ver_init;	/* 0:7 crc, 8:15 ver, 16:31 sdram_init */
+	uint32_t config_refresh;	/* 0:15 sdram_config, 16:31 sdram_refresh */
+	uint32_t config_ncdl;	/* ncdl values for memc */
+} __attribute__((__packed__));
+
+struct nvram_tuple {
+	char *name;
+	char *value;
+	struct nvram_tuple *next;
+};
+
+struct nvram_handle {
+	int fd;
+	char *mmap;
+	unsigned int length;
+	unsigned int offset;
+	struct nvram_tuple *nvram_hash[257];
+	struct nvram_tuple *nvram_dead;
+};
+
+typedef struct nvram_handle nvram_handle_t;
+typedef struct nvram_header nvram_header_t;
+typedef struct nvram_tuple  nvram_tuple_t;
+
+
+/* Get nvram header. */
+nvram_header_t * nvram_header(nvram_handle_t *h);
+
+/* Set the value of an NVRAM variable */
+int nvram_set(nvram_handle_t *h, const char *name, const char *value);
+
+/* Get the value of an NVRAM variable. */
+char * nvram_get(nvram_handle_t *h, const char *name);
+
+/* Unset the value of an NVRAM variable. */
+int nvram_unset(nvram_handle_t *h, const char *name);
+
+/* Get all NVRAM variables. */
+nvram_tuple_t * nvram_getall(nvram_handle_t *h);
+
+/* Regenerate NVRAM. */
+int nvram_commit(nvram_handle_t *h);
+
+/* Open NVRAM and obtain a handle. */
+nvram_handle_t * nvram_open(const char *file, int rdonly);
+
+/* Close NVRAM and free memory. */
+int nvram_close(nvram_handle_t *h);
+
+/* Get the value of an NVRAM variable in a safe way, use "" instead of NULL. */
+#define nvram_safe_get(h, name) (nvram_get(h, name) ? : "")
+
+/* Computes a crc8 over the input data. */
+uint8_t hndcrc8 (uint8_t * pdata, uint32_t nbytes, uint8_t crc);
+
+/* Returns the crc value of the nvram. */
+uint8_t nvram_calc_crc(nvram_header_t * nvh);
+
+/* Determine NVRAM device node. */
+char * nvram_find_mtd(void);
+
+/* Copy NVRAM contents to staging file. */
+int nvram_to_staging(void);
+
+/* Copy staging file to NVRAM device. */
+int staging_to_nvram(void);
+
+/* Check NVRAM staging file. */
+char * nvram_find_staging(void);
+
+
+/* Staging file for NVRAM */
+#define NVRAM_STAGING		"/tmp/.nvram"
+#define NVRAM_RO			1
+#define NVRAM_RW			0
+
+/* Helper macros */
+#define NVRAM_ARRAYSIZE(a)	sizeof(a)/sizeof(a[0])
+#define	NVRAM_ROUNDUP(x, y)	((((x)+((y)-1))/(y))*(y))
+
+/* NVRAM constants */
+#define NVRAM_MIN_SPACE			0x8000
+#define NVRAM_MAGIC			0x48534C46	/* 'FLSH' */
+#define NVRAM_VERSION		1
+
+#define NVRAM_CRC_START_POSITION	9 /* magic, len, crc8 to be skipped */
+
+
+#endif /* _nvram_h_ */
diff --git a/package/utils/nvram/src/sdinitvals.h b/package/utils/nvram/src/sdinitvals.h
new file mode 100644
index 0000000..5a289ad
--- /dev/null
+++ b/package/utils/nvram/src/sdinitvals.h
@@ -0,0 +1,30 @@
+/*
+ * SDRAM init values
+ *
+ * Copyright 2007, Broadcom Corporation
+ * Copyright 2009, OpenWrt.org
+ * All Rights Reserved.
+ *
+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
+ *
+ */
+
+#ifndef _sdinitvals_h_
+#define _sdinitvals_h_
+
+/* SDRAM refresh control (refresh) register bits */
+#define SDRAM_REF(p)    (((p)&0xff) | SDRAM_REF_EN)     /* Refresh period */
+#define SDRAM_REF_EN    0x8000          /* Writing 1 enables periodic refresh */
+
+/* SDRAM Core default Init values (OCP ID 0x803) */
+#define MEM4MX16X2      0x419   /* 16 MB */
+
+#define SDRAM_INIT	MEM4MX16X2
+#define SDRAM_BURSTFULL 0x0000  /* Use full page bursts */
+#define SDRAM_CONFIG    SDRAM_BURSTFULL
+#define SDRAM_REFRESH   SDRAM_REF(0x40)
+
+#endif /* _sdinitvals_h_ */
diff --git a/package/utils/osafeloader/Makefile b/package/utils/osafeloader/Makefile
new file mode 100644
index 0000000..d0a590e
--- /dev/null
+++ b/package/utils/osafeloader/Makefile
@@ -0,0 +1,40 @@
+#
+# Copyright (C) 2016 Rafał Miłecki <rafal@milecki.pl>
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=osafeloader
+PKG_RELEASE:=1
+
+PKG_FLAGS:=nonshared
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/osafeloader
+  SECTION:=utils
+  CATEGORY:=Base system
+  TITLE:=Utility for handling TP-LINK SafeLoader images
+  MAINTAINER:=Rafał Miłecki <rafal@milecki.pl>
+  DEPENDS:=@TARGET_bcm53xx
+endef
+
+define Package/osafeloader/description
+ This package contains an utility that allows handling SafeLoader images.
+endef
+
+define Build/Compile
+	$(MAKE) -C $(PKG_BUILD_DIR) \
+		CC="$(TARGET_CC)" \
+		CFLAGS="$(TARGET_CFLAGS) -Wall"
+endef
+
+define Package/osafeloader/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/osafeloader $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,osafeloader))
diff --git a/package/utils/osafeloader/src/Makefile b/package/utils/osafeloader/src/Makefile
new file mode 100644
index 0000000..acc6f0f
--- /dev/null
+++ b/package/utils/osafeloader/src/Makefile
@@ -0,0 +1,7 @@
+all: osafeloader
+
+osafeloader:
+	$(CC) $(CFLAGS) -Wall osafeloader.c md5.c -o $@ $^
+
+clean:
+	rm -f osafeloader
diff --git a/package/utils/osafeloader/src/md5.c b/package/utils/osafeloader/src/md5.c
new file mode 100644
index 0000000..52d96ac
--- /dev/null
+++ b/package/utils/osafeloader/src/md5.c
@@ -0,0 +1,296 @@
+/*
+ * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
+ * MD5 Message-Digest Algorithm (RFC 1321).
+ *
+ * Homepage:
+ * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
+ *
+ * Author:
+ * Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
+ *
+ * This software was written by Alexander Peslyak in 2001.  No copyright is
+ * claimed, and the software is hereby placed in the public domain.
+ * In case this attempt to disclaim copyright and place the software in the
+ * public domain is deemed null and void, then the software is
+ * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
+ * general public under the following terms:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted.
+ *
+ * There's ABSOLUTELY NO WARRANTY, express or implied.
+ *
+ * (This is a heavily cut-down "BSD license".)
+ *
+ * This differs from Colin Plumb's older public domain implementation in that
+ * no exactly 32-bit integer data type is required (any 32-bit or wider
+ * unsigned integer data type will do), there's no compile-time endianness
+ * configuration, and the function prototypes match OpenSSL's.  No code from
+ * Colin Plumb's implementation has been reused; this comment merely compares
+ * the properties of the two independent implementations.
+ *
+ * The primary goals of this implementation are portability and ease of use.
+ * It is meant to be fast, but not as fast as possible.  Some known
+ * optimizations are not included to reduce source code size and avoid
+ * compile-time configuration.
+ */
+
+#ifndef HAVE_OPENSSL
+
+#include <string.h>
+
+#include "md5.h"
+
+/*
+ * The basic MD5 functions.
+ *
+ * F and G are optimized compared to their RFC 1321 definitions for
+ * architectures that lack an AND-NOT instruction, just like in Colin Plumb's
+ * implementation.
+ */
+#define F(x, y, z)			((z) ^ ((x) & ((y) ^ (z))))
+#define G(x, y, z)			((y) ^ ((z) & ((x) ^ (y))))
+#define H(x, y, z)			(((x) ^ (y)) ^ (z))
+#define H2(x, y, z)			((x) ^ ((y) ^ (z)))
+#define I(x, y, z)			((y) ^ ((x) | ~(z)))
+
+/*
+ * The MD5 transformation for all four rounds.
+ */
+#define STEP(f, a, b, c, d, x, t, s) \
+	(a) += f((b), (c), (d)) + (x) + (t); \
+	(a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \
+	(a) += (b);
+
+/*
+ * SET reads 4 input bytes in little-endian byte order and stores them
+ * in a properly aligned word in host byte order.
+ *
+ * The check for little-endian architectures that tolerate unaligned
+ * memory accesses is just an optimization.  Nothing will break if it
+ * doesn't work.
+ */
+#if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
+#define SET(n) \
+	(*(MD5_u32plus *)&ptr[(n) * 4])
+#define GET(n) \
+	SET(n)
+#else
+#define SET(n) \
+	(ctx->block[(n)] = \
+	(MD5_u32plus)ptr[(n) * 4] | \
+	((MD5_u32plus)ptr[(n) * 4 + 1] << 8) | \
+	((MD5_u32plus)ptr[(n) * 4 + 2] << 16) | \
+	((MD5_u32plus)ptr[(n) * 4 + 3] << 24))
+#define GET(n) \
+	(ctx->block[(n)])
+#endif
+
+/*
+ * This processes one or more 64-byte data blocks, but does NOT update
+ * the bit counters.  There are no alignment requirements.
+ */
+static const void *body(MD5_CTX *ctx, const void *data, unsigned long size)
+{
+	const unsigned char *ptr;
+	MD5_u32plus a, b, c, d;
+	MD5_u32plus saved_a, saved_b, saved_c, saved_d;
+
+	ptr = (const unsigned char *)data;
+
+	a = ctx->a;
+	b = ctx->b;
+	c = ctx->c;
+	d = ctx->d;
+
+	do {
+		saved_a = a;
+		saved_b = b;
+		saved_c = c;
+		saved_d = d;
+
+/* Round 1 */
+		STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
+		STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
+		STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
+		STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
+		STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
+		STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
+		STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
+		STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
+		STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
+		STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
+		STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
+		STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
+		STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
+		STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
+		STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
+		STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)
+
+/* Round 2 */
+		STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
+		STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
+		STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
+		STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
+		STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
+		STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
+		STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
+		STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
+		STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
+		STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
+		STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
+		STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
+		STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
+		STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
+		STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
+		STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)
+
+/* Round 3 */
+		STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
+		STEP(H2, d, a, b, c, GET(8), 0x8771f681, 11)
+		STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
+		STEP(H2, b, c, d, a, GET(14), 0xfde5380c, 23)
+		STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
+		STEP(H2, d, a, b, c, GET(4), 0x4bdecfa9, 11)
+		STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
+		STEP(H2, b, c, d, a, GET(10), 0xbebfbc70, 23)
+		STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
+		STEP(H2, d, a, b, c, GET(0), 0xeaa127fa, 11)
+		STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
+		STEP(H2, b, c, d, a, GET(6), 0x04881d05, 23)
+		STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
+		STEP(H2, d, a, b, c, GET(12), 0xe6db99e5, 11)
+		STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
+		STEP(H2, b, c, d, a, GET(2), 0xc4ac5665, 23)
+
+/* Round 4 */
+		STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
+		STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
+		STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
+		STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
+		STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
+		STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
+		STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
+		STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
+		STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
+		STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
+		STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
+		STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
+		STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
+		STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
+		STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
+		STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)
+
+		a += saved_a;
+		b += saved_b;
+		c += saved_c;
+		d += saved_d;
+
+		ptr += 64;
+	} while (size -= 64);
+
+	ctx->a = a;
+	ctx->b = b;
+	ctx->c = c;
+	ctx->d = d;
+
+	return ptr;
+}
+
+void MD5_Init(MD5_CTX *ctx)
+{
+	ctx->a = 0x67452301;
+	ctx->b = 0xefcdab89;
+	ctx->c = 0x98badcfe;
+	ctx->d = 0x10325476;
+
+	ctx->lo = 0;
+	ctx->hi = 0;
+}
+
+void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size)
+{
+	MD5_u32plus saved_lo;
+	unsigned long used, available;
+
+	saved_lo = ctx->lo;
+	if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
+		ctx->hi++;
+	ctx->hi += size >> 29;
+
+	used = saved_lo & 0x3f;
+
+	if (used) {
+		available = 64 - used;
+
+		if (size < available) {
+			memcpy(&ctx->buffer[used], data, size);
+			return;
+		}
+
+		memcpy(&ctx->buffer[used], data, available);
+		data = (const unsigned char *)data + available;
+		size -= available;
+		body(ctx, ctx->buffer, 64);
+	}
+
+	if (size >= 64) {
+		data = body(ctx, data, size & ~(unsigned long)0x3f);
+		size &= 0x3f;
+	}
+
+	memcpy(ctx->buffer, data, size);
+}
+
+void MD5_Final(unsigned char *result, MD5_CTX *ctx)
+{
+	unsigned long used, available;
+
+	used = ctx->lo & 0x3f;
+
+	ctx->buffer[used++] = 0x80;
+
+	available = 64 - used;
+
+	if (available < 8) {
+		memset(&ctx->buffer[used], 0, available);
+		body(ctx, ctx->buffer, 64);
+		used = 0;
+		available = 64;
+	}
+
+	memset(&ctx->buffer[used], 0, available - 8);
+
+	ctx->lo <<= 3;
+	ctx->buffer[56] = ctx->lo;
+	ctx->buffer[57] = ctx->lo >> 8;
+	ctx->buffer[58] = ctx->lo >> 16;
+	ctx->buffer[59] = ctx->lo >> 24;
+	ctx->buffer[60] = ctx->hi;
+	ctx->buffer[61] = ctx->hi >> 8;
+	ctx->buffer[62] = ctx->hi >> 16;
+	ctx->buffer[63] = ctx->hi >> 24;
+
+	body(ctx, ctx->buffer, 64);
+
+	result[0] = ctx->a;
+	result[1] = ctx->a >> 8;
+	result[2] = ctx->a >> 16;
+	result[3] = ctx->a >> 24;
+	result[4] = ctx->b;
+	result[5] = ctx->b >> 8;
+	result[6] = ctx->b >> 16;
+	result[7] = ctx->b >> 24;
+	result[8] = ctx->c;
+	result[9] = ctx->c >> 8;
+	result[10] = ctx->c >> 16;
+	result[11] = ctx->c >> 24;
+	result[12] = ctx->d;
+	result[13] = ctx->d >> 8;
+	result[14] = ctx->d >> 16;
+	result[15] = ctx->d >> 24;
+
+	memset(ctx, 0, sizeof(*ctx));
+}
+
+#endif
diff --git a/package/utils/osafeloader/src/md5.h b/package/utils/osafeloader/src/md5.h
new file mode 100644
index 0000000..2da44bf
--- /dev/null
+++ b/package/utils/osafeloader/src/md5.h
@@ -0,0 +1,45 @@
+/*
+ * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
+ * MD5 Message-Digest Algorithm (RFC 1321).
+ *
+ * Homepage:
+ * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
+ *
+ * Author:
+ * Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
+ *
+ * This software was written by Alexander Peslyak in 2001.  No copyright is
+ * claimed, and the software is hereby placed in the public domain.
+ * In case this attempt to disclaim copyright and place the software in the
+ * public domain is deemed null and void, then the software is
+ * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
+ * general public under the following terms:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted.
+ *
+ * There's ABSOLUTELY NO WARRANTY, express or implied.
+ *
+ * See md5.c for more information.
+ */
+
+#ifdef HAVE_OPENSSL
+#include <openssl/md5.h>
+#elif !defined(_MD5_H)
+#define _MD5_H
+
+/* Any 32-bit or wider unsigned integer data type will do */
+typedef unsigned int MD5_u32plus;
+
+typedef struct {
+	MD5_u32plus lo, hi;
+	MD5_u32plus a, b, c, d;
+	unsigned char buffer[64];
+	MD5_u32plus block[16];
+} MD5_CTX;
+
+extern void MD5_Init(MD5_CTX *ctx);
+extern void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size);
+extern void MD5_Final(unsigned char *result, MD5_CTX *ctx);
+
+#endif
diff --git a/package/utils/osafeloader/src/osafeloader.c b/package/utils/osafeloader/src/osafeloader.c
new file mode 100644
index 0000000..9ffa5fe
--- /dev/null
+++ b/package/utils/osafeloader/src/osafeloader.c
@@ -0,0 +1,263 @@
+/*
+ * osafeloader
+ *
+ * Copyright (C) 2016 Rafał Miłecki <zajec5@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <byteswap.h>
+#include <endian.h>
+#include <errno.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "md5.h"
+
+#if !defined(__BYTE_ORDER)
+#error "Unknown byte order"
+#endif
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+#define cpu_to_be32(x)	(x)
+#define be32_to_cpu(x)	(x)
+#define cpu_to_be16(x)	(x)
+#define be16_to_cpu(x)	(x)
+#elif __BYTE_ORDER == __LITTLE_ENDIAN
+#define cpu_to_be32(x)	bswap_32(x)
+#define be32_to_cpu(x)	bswap_32(x)
+#define cpu_to_be16(x)	bswap_16(x)
+#define be16_to_cpu(x)	bswap_16(x)
+#else
+#error "Unsupported endianness"
+#endif
+
+struct safeloader_header {
+	uint32_t imagesize;
+	uint8_t md5[16];
+} __attribute__ ((packed));
+
+char *safeloader_path;
+char *partition_name;
+char *out_path;
+
+static inline size_t osafeloader_min(size_t x, size_t y) {
+	return x < y ? x : y;
+}
+
+static const uint8_t md5_salt[16] = {
+	0x7a, 0x2b, 0x15, 0xed,
+	0x9b, 0x98, 0x59, 0x6d,
+	0xe5, 0x04, 0xab, 0x44,
+	0xac, 0x2a, 0x9f, 0x4e,
+};
+
+/**************************************************
+ * Info
+ **************************************************/
+
+static int osafeloader_info(int argc, char **argv) {
+	FILE *safeloader;
+	struct safeloader_header hdr;
+	MD5_CTX ctx;
+	size_t bytes, imagesize;
+	uint8_t buf[1024];
+	uint8_t md5[16];
+	char name[32];
+	int base, size, i;
+	int err = 0;
+
+	if (argc < 3) {
+		fprintf(stderr, "No SafeLoader file passed\n");
+		err = -EINVAL;
+		goto out;
+	}
+	safeloader_path = argv[2];
+
+	safeloader = fopen(safeloader_path, "r");
+	if (!safeloader) {
+		fprintf(stderr, "Couldn't open %s\n", safeloader_path);
+		err = -EACCES;
+		goto out;
+	}
+
+	bytes = fread(&hdr, 1, sizeof(hdr), safeloader);
+	if (bytes != sizeof(hdr)) {
+		fprintf(stderr, "Couldn't read %s header\n", safeloader_path);
+		err =  -EIO;
+		goto err_close;
+	}
+	imagesize = be32_to_cpu(hdr.imagesize);
+
+	MD5_Init(&ctx);
+	MD5_Update(&ctx, md5_salt, sizeof(md5_salt));
+	while ((bytes = fread(buf, 1, osafeloader_min(sizeof(buf), imagesize), safeloader)) > 0) {
+		MD5_Update(&ctx, buf, bytes);
+		imagesize -= bytes;
+	}
+	MD5_Final(md5, &ctx);
+
+	if (memcmp(md5, hdr.md5, 16)) {
+		fprintf(stderr, "Broken SafeLoader file with invalid MD5\n");
+		err =  -EIO;
+		goto err_close;
+	}
+
+	printf("%10s: %d\n", "Image size", be32_to_cpu(hdr.imagesize));
+	printf("%10s: ", "MD5");
+	for (i = 0; i < 16; i++)
+		printf("%02x", md5[i]);
+	printf("\n");
+
+	/* Skip header & vendor info */
+	fseek(safeloader, 0x1014, SEEK_SET);
+
+	while (fscanf(safeloader, "fwup-ptn %s base 0x%x size 0x%x\t\r\n", name, &base, &size) == 3) {
+		printf("%10s: %s (0x%x - 0x%x)\n", "Partition", name, base, base + size);
+	}
+
+err_close:
+	fclose(safeloader);
+out:
+	return err;
+}
+
+/**************************************************
+ * Extract
+ **************************************************/
+
+static void osafeloader_extract_parse_options(int argc, char **argv) {
+	int c;
+
+	while ((c = getopt(argc, argv, "p:o:")) != -1) {
+		switch (c) {
+		case 'p':
+			partition_name = optarg;
+			break;
+		case 'o':
+			out_path = optarg;
+			break;
+		}
+	}
+}
+
+static int osafeloader_extract(int argc, char **argv) {
+	FILE *safeloader;
+	FILE *out;
+	struct safeloader_header hdr;
+	size_t bytes;
+	char name[32];
+	int base, size;
+	int err = 0;
+
+	if (argc < 3) {
+		fprintf(stderr, "No SafeLoader file passed\n");
+		err = -EINVAL;
+		goto out;
+	}
+	safeloader_path = argv[2];
+
+	optind = 3;
+	osafeloader_extract_parse_options(argc, argv);
+	if (!partition_name) {
+		fprintf(stderr, "No partition name specified\n");
+		err = -EINVAL;
+		goto out;
+	} else if (!out_path) {
+		fprintf(stderr, "No output file specified\n");
+		err = -EINVAL;
+		goto out;
+	}
+
+	safeloader = fopen(safeloader_path, "r");
+	if (!safeloader) {
+		fprintf(stderr, "Couldn't open %s\n", safeloader_path);
+		err = -EACCES;
+		goto out;
+	}
+
+	out = fopen(out_path, "w");
+	if (!out) {
+		fprintf(stderr, "Couldn't open %s\n", out_path);
+		err = -EACCES;
+		goto err_close_safeloader;
+	}
+
+	bytes = fread(&hdr, 1, sizeof(hdr), safeloader);
+	if (bytes != sizeof(hdr)) {
+		fprintf(stderr, "Couldn't read %s header\n", safeloader_path);
+		err =  -EIO;
+		goto err_close_out;
+	}
+
+	/* Skip vendor info */
+	fseek(safeloader, 0x1000, SEEK_CUR);
+
+	err = -ENOENT;
+	while (fscanf(safeloader, "fwup-ptn %s base 0x%x size 0x%x\t\r\n", name, &base, &size) == 3) {
+		uint8_t buf[1024];
+
+		if (strcmp(name, partition_name))
+			continue;
+
+		err = 0;
+
+		fseek(safeloader, sizeof(hdr) + 0x1000 + base, SEEK_SET);
+
+		while ((bytes = fread(buf, 1, osafeloader_min(sizeof(buf), size), safeloader)) > 0) {
+			if (fwrite(buf, 1, bytes, out) != bytes) {
+				fprintf(stderr, "Couldn't write %zu B to %s\n", bytes, out_path);
+				err = -EIO;
+				break;
+			}
+			size -= bytes;
+		}
+
+		if (size) {
+			fprintf(stderr, "Couldn't extract whole partition %s from %s (%d B left)\n", partition_name, safeloader_path, size);
+			err = -EIO;
+		}
+
+		break;
+	}
+
+err_close_out:
+	fclose(out);
+err_close_safeloader:
+	fclose(safeloader);
+out:
+	return err;
+}
+
+/**************************************************
+ * Start
+ **************************************************/
+
+static void usage() {
+	printf("Usage:\n");
+	printf("\n");
+	printf("Info about SafeLoader:\n");
+	printf("\tosafeloader info <file>\n");
+	printf("\n");
+	printf("Extract from SafeLoader:\n");
+	printf("\tosafeloader extract <file> [options]\n");
+	printf("\t-p name\t\t\t\tname of partition to extract\n");
+	printf("\t-o file\t\t\t\toutput file\n");
+}
+
+int main(int argc, char **argv) {
+	if (argc > 1) {
+		if (!strcmp(argv[1], "info"))
+			return osafeloader_info(argc, argv);
+		else if (!strcmp(argv[1], "extract"))
+			return osafeloader_extract(argc, argv);
+	}
+
+	usage();
+	return 0;
+}
diff --git a/package/utils/pciutils/Makefile b/package/utils/pciutils/Makefile
new file mode 100644
index 0000000..870ffae
--- /dev/null
+++ b/package/utils/pciutils/Makefile
@@ -0,0 +1,86 @@
+#
+# Copyright (C) 2007-2017 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=pciutils
+PKG_VERSION:=3.8.0
+PKG_RELEASE:=2
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=@KERNEL/software/utils/pciutils
+PKG_HASH:=91edbd0429a84705c9ad156d4ff38ccc724d41ea54c4c5b88e38e996f8a34f05
+
+PKG_MAINTAINER:=Lucian Cristian <lucian.cristian@gmail.com>
+PKG_LICENSE:=GPL-2.0
+PKG_LICENSE_FILES:=COPYING
+PKG_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/pciutils
+  SECTION:=utils
+  CATEGORY:=Utilities
+  TITLE:=Linux PCI Utilities
+  URL:=http://mj.ucw.cz/pciutils.shtml
+  DEPENDS:=+libkmod +libpci +pciids
+endef
+
+define Package/pciutils/description
+ contains collection of programs for inspecting and manipulating configuration
+ of PCI devices
+endef
+
+define Package/libpci
+  SECTION:=libs
+  CATEGORY:=Libraries
+  TITLE:=Linux PCI Libraries
+  URL:=http://mj.ucw.cz/pciutils.shtml
+endef
+
+TARGET_CFLAGS += $(FPIC)
+
+MAKE_FLAGS += \
+	CFLAGS="$(TARGET_CFLAGS) $(TARGET_CPPFLAGS)" \
+	PREFIX="/usr" \
+	HOST="Linux" \
+	HWDB="no" \
+	ZLIB="no" \
+	SHARED="yes"
+
+ifneq ($(CONFIG_USE_GLIBC),)
+TARGET_LDFLAGS += -lresolv
+endif
+
+define Build/InstallDev
+	$(INSTALL_DIR) $(1)/usr/lib
+	$(CP) $(PKG_INSTALL_DIR)/usr/lib/libpci.so.3 \
+		$(PKG_INSTALL_DIR)/usr/lib/libpci.so
+	$(CP) $(PKG_INSTALL_DIR)/usr/lib/*.so* $(1)/usr/lib
+	$(INSTALL_DIR) $(1)/usr/lib/pkgconfig
+	$(CP) $(PKG_BUILD_DIR)/lib/libpci.pc $(1)/usr/lib/pkgconfig
+	$(SED) 's,/usr/include,$$$${prefix}/include,g' $(1)/usr/lib/pkgconfig/libpci.pc
+	$(SED) 's,/usr/lib,$$$${prefix}/lib,g' $(1)/usr/lib/pkgconfig/libpci.pc
+	$(INSTALL_DIR) $(1)/usr/include/pci
+	$(CP) $(foreach i,pci.h config.h header.h types.h, \
+		$(PKG_BUILD_DIR)/lib/$(i)) $(1)/usr/include/pci
+endef
+
+define Package/pciutils/install
+	$(INSTALL_DIR) $(1)/usr/sbin $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/lspci $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/setpci $(1)/usr/sbin/
+endef
+
+define Package/libpci/install
+	$(INSTALL_DIR) $(1)/usr/lib
+	$(CP) $(PKG_INSTALL_DIR)/usr/lib/*.so* $(1)/usr/lib/
+endef
+
+
+$(eval $(call BuildPackage,libpci))
+$(eval $(call BuildPackage,pciutils))
diff --git a/package/utils/pciutils/patches/101-no-strip.patch b/package/utils/pciutils/patches/101-no-strip.patch
new file mode 100644
index 0000000..827a453
--- /dev/null
+++ b/package/utils/pciutils/patches/101-no-strip.patch
@@ -0,0 +1,13 @@
+--- a/Makefile
++++ b/Makefile
+@@ -131,8 +131,8 @@ distclean: clean
+ install: all
+ # -c is ignored on Linux, but required on FreeBSD
+ 	$(DIRINSTALL) -m 755 $(DESTDIR)$(BINDIR) $(DESTDIR)$(SBINDIR) $(DESTDIR)$(IDSDIR) $(DESTDIR)$(MANDIR)/man8 $(DESTDIR)$(MANDIR)/man7 $(DESTDIR)/$(MANDIR)/man5
+-	$(INSTALL) -c -m 755 $(STRIP) lspci$(EXEEXT) $(DESTDIR)$(LSPCIDIR)
+-	$(INSTALL) -c -m 755 $(STRIP) setpci$(EXEEXT) $(DESTDIR)$(SBINDIR)
++	$(INSTALL) -c -m 755 lspci$(EXEEXT) $(DESTDIR)$(LSPCIDIR)
++	$(INSTALL) -c -m 755 setpci$(EXEEXT) $(DESTDIR)$(SBINDIR)
+ 	$(INSTALL) -c -m 755 update-pciids $(DESTDIR)$(SBINDIR)
+ 	$(INSTALL) -c -m 644 $(PCI_IDS) $(DESTDIR)$(IDSDIR)
+ 	$(INSTALL) -c -m 644 lspci.8 setpci.8 update-pciids.8 $(DESTDIR)$(MANDIR)/man8
diff --git a/package/utils/pciutils/patches/104-resolv.patch b/package/utils/pciutils/patches/104-resolv.patch
new file mode 100644
index 0000000..485e1b9
--- /dev/null
+++ b/package/utils/pciutils/patches/104-resolv.patch
@@ -0,0 +1,11 @@
+--- a/lib/configure
++++ b/lib/configure
+@@ -60,7 +60,7 @@ echo >>$c "#define PCI_OS_`echo $sys | t
+ echo >$m 'WITH_LIBS='
+ 
+ echo_n "Looking for access methods..."
+-LIBRESOLV=-lresolv
++LIBRESOLV=
+ LIBEXT=so
+ EXEEXT=
+ SYSINCLUDE=/usr/include
diff --git a/package/utils/pciutils/patches/106-hwdata.patch b/package/utils/pciutils/patches/106-hwdata.patch
new file mode 100644
index 0000000..e18ef78
--- /dev/null
+++ b/package/utils/pciutils/patches/106-hwdata.patch
@@ -0,0 +1,11 @@
+--- a/Makefile
++++ b/Makefile
+@@ -36,7 +36,7 @@ PREFIX=/usr/local
+ BINDIR=$(PREFIX)/bin
+ SBINDIR=$(PREFIX)/sbin
+ SHAREDIR=$(PREFIX)/share
+-IDSDIR=$(SHAREDIR)
++IDSDIR=$(SHAREDIR)/hwdata
+ MANDIR:=$(shell if [ -d $(PREFIX)/share/man ] ; then echo $(PREFIX)/share/man ; else echo $(PREFIX)/man ; fi)
+ INCDIR=$(PREFIX)/include
+ LIBDIR=$(PREFIX)/lib
diff --git a/package/utils/pciutils/patches/107-avoid-addng-multiple-version-tags.patch b/package/utils/pciutils/patches/107-avoid-addng-multiple-version-tags.patch
new file mode 100644
index 0000000..74b5782
--- /dev/null
+++ b/package/utils/pciutils/patches/107-avoid-addng-multiple-version-tags.patch
@@ -0,0 +1,42 @@
+From 0478e1f3928bfaa34eb910ba2cbaf1dda8f84aab Mon Sep 17 00:00:00 2001
+From: Martin Mares <mj@ucw.cz>
+Date: Wed, 10 Aug 2022 13:34:28 +0700
+Subject: [PATCH] Avoid adding multiple version tags to the same symbol
+
+This is apparently forbidden in most versions of binutils.
+---
+ lib/filter.c | 12 ++++++++----
+ 1 file changed, 8 insertions(+), 4 deletions(-)
+
+--- a/lib/filter.c
++++ b/lib/filter.c
+@@ -303,21 +303,25 @@ pci_filter_match_v30(struct pci_filter_v
+ // (their positions in struct pci_filter were declared as RFU).
+ 
+ STATIC_ALIAS(void pci_filter_init(struct pci_access *a, struct pci_filter *f), pci_filter_init_v38(a, f));
++DEFINE_ALIAS(void pci_filter_init_v33(struct pci_access *a, struct pci_filter *f), pci_filter_init_v38);
+ SYMBOL_VERSION(pci_filter_init_v30, pci_filter_init@LIBPCI_3.0);
+-SYMBOL_VERSION(pci_filter_init_v38, pci_filter_init@LIBPCI_3.3);
++SYMBOL_VERSION(pci_filter_init_v33, pci_filter_init@LIBPCI_3.3);
+ SYMBOL_VERSION(pci_filter_init_v38, pci_filter_init@@LIBPCI_3.8);
+ 
+ STATIC_ALIAS(char *pci_filter_parse_slot(struct pci_filter *f, char *str), pci_filter_parse_slot_v38(f, str));
++DEFINE_ALIAS(char *pci_filter_parse_slot_v33(struct pci_filter *f, char *str), pci_filter_parse_slot_v38);
+ SYMBOL_VERSION(pci_filter_parse_slot_v30, pci_filter_parse_slot@LIBPCI_3.0);
+-SYMBOL_VERSION(pci_filter_parse_slot_v38, pci_filter_parse_slot@LIBPCI_3.3);
++SYMBOL_VERSION(pci_filter_parse_slot_v33, pci_filter_parse_slot@LIBPCI_3.3);
+ SYMBOL_VERSION(pci_filter_parse_slot_v38, pci_filter_parse_slot@@LIBPCI_3.8);
+ 
+ STATIC_ALIAS(char *pci_filter_parse_id(struct pci_filter *f, char *str), pci_filter_parse_id_v38(f, str));
++DEFINE_ALIAS(char *pci_filter_parse_id_v33(struct pci_filter *f, char *str), pci_filter_parse_id_v38);
+ SYMBOL_VERSION(pci_filter_parse_id_v30, pci_filter_parse_id@LIBPCI_3.0);
+-SYMBOL_VERSION(pci_filter_parse_id_v38, pci_filter_parse_id@LIBPCI_3.3);
++SYMBOL_VERSION(pci_filter_parse_id_v33, pci_filter_parse_id@LIBPCI_3.3);
+ SYMBOL_VERSION(pci_filter_parse_id_v38, pci_filter_parse_id@@LIBPCI_3.8);
+ 
+ STATIC_ALIAS(int pci_filter_match(struct pci_filter *f, struct pci_dev *d), pci_filter_match_v38(f, d));
++DEFINE_ALIAS(int pci_filter_match_v33(struct pci_filter *f, struct pci_dev *d), pci_filter_match_v38);
+ SYMBOL_VERSION(pci_filter_match_v30, pci_filter_match@LIBPCI_3.0);
+-SYMBOL_VERSION(pci_filter_match_v38, pci_filter_match@LIBPCI_3.3);
++SYMBOL_VERSION(pci_filter_match_v33, pci_filter_match@LIBPCI_3.3);
+ SYMBOL_VERSION(pci_filter_match_v38, pci_filter_match@@LIBPCI_3.8);
diff --git a/package/utils/policycoreutils/Makefile b/package/utils/policycoreutils/Makefile
new file mode 100644
index 0000000..5ca322b
--- /dev/null
+++ b/package/utils/policycoreutils/Makefile
@@ -0,0 +1,146 @@
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=policycoreutils
+PKG_VERSION:=3.5
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://github.com/SELinuxProject/selinux/releases/download/$(PKG_VERSION)
+PKG_HASH:=78453e1529fbbf800e88860094d555e781ce1fba11a7ef77b5aabb43e1173276
+PKG_INSTALL:=1
+HOST_BUILD_DEPENDS:=libsemanage/host BUILD_NLS:gettext-full/host
+PKG_BUILD_DEPENDS:=BUSYBOX_CONFIG_PAM:libpam BUILD_NLS:gettext-full/host
+
+PKG_MAINTAINER:=Thomas Petazzoni <thomas.petazzoni@bootlin.com>
+PKG_CPE_ID:=cpe:/a:selinuxproject:policycoreutils
+PKG_LICENSE:=GPL-2.0-or-later
+PKG_LICENSE_FILES:=COPYING
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/nls.mk
+include $(INCLUDE_DIR)/host-build.mk
+
+DIR_USR_BIN:= \
+	newrole \
+	secon \
+	sestatus
+
+DIR_USR_SBIN:= \
+	load_policy \
+	setsebool
+
+LIBEXEC_UTILS := \
+	pp
+
+SBIN_UTILS:= \
+	restorecon_xattr \
+	setfiles
+
+USR_BIN_UTILS:= \
+	newrole \
+	secon \
+	sestatus
+
+USR_SBIN_UTILS:= \
+	fixfiles \
+	genhomedircon \
+	open_init_pty \
+	run_init \
+	semodule \
+	load_policy \
+	setsebool
+
+TARGET_LDFLAGS += $(INTL_LDFLAGS) $(if $(INTL_FULL),-lintl)
+
+MAKE_FLAGS += \
+	PAMH=$(CONFIG_BUSYBOX_CONFIG_PAM)
+
+HOST_MAKE_FLAGS += \
+	PAMH=$(CONFIG_BUSYBOX_CONFIG_PAM) \
+	DESTDIR=$(STAGING_DIR_HOST) \
+	PREFIX= \
+	SBINDIR=/bin
+
+HOST_LDFLAGS += -Wl,-rpath=$(STAGING_DIR_HOSTPKG)/lib
+
+$(eval $(foreach a,$(DIR_SBIN),ALTS_$(a):=300:/sbin/$(a):/sbin/policycoreutils-$(a)$(newline)))
+$(eval $(foreach a,$(DIR_USR_BIN),ALTS_$(a):=300:/usr/bin/$(a):/usr/bin/policycoreutils-$(a)$(newline)))
+$(eval $(foreach a,$(DIR_USR_SBIN),ALTS_$(a):=300:/usr/sbin/$(a):/usr/sbin/policycoreutils-$(a)$(newline)))
+ALTS_setfiles:=300:/sbin/restorecon:/sbin/policycoreutils-setfiles 300:/sbin/setfiles:/sbin/policycoreutils-setfiles
+
+DEPENDS_genhomedircon:=+libsemanage $(INTL_DEPENDS)
+DEPENDS_load_policy:=+libselinux $(INTL_DEPENDS)
+DEPENDS_newrole:=+libselinux +libaudit +BUSYBOX_CONFIG_PAM:libpam $(INTL_DEPENDS)
+DEPENDS_open_init_pty:=$(INTL_DEPENDS)
+DEPENDS_pp:=+libsepol $(INTL_DEPENDS)
+DEPENDS_restorecon_xattr:=+libselinux +libsepol +libaudit $(INTL_DEPENDS)
+DEPENDS_run_init:=+libselinux +libaudit +BUSYBOX_CONFIG_PAM:libpam $(INTL_DEPENDS)
+DEPENDS_secon:=+libselinux $(INTL_DEPENDS)
+DEPENDS_semanage:=+libsemanage
+DEPENDS_semodule:=+libsemanage $(INTL_DEPENDS)
+DEPENDS_sestatus:=+libselinux $(INTL_DEPENDS)
+DEPENDS_setfiles:=+libselinux +libsepol +libaudit $(INTL_DEPENDS)
+DEPENDS_setsebool:=+libsemanage $(INTL_DEPENDS)
+
+define Package/policycoreutils/Default
+  SECTION:=utils
+  CATEGORY:=Utilities
+  TITLE:=SELinux policy utility
+  URL:=http://selinuxproject.org/page/Main_Page
+endef
+
+define Package/policycoreutils
+  $(call Package/policycoreutils/Default)
+  MENU:=1
+  TITLE+= common files
+endef
+
+define GenUtilPkg
+  define Package/$(1)
+    $(call Package/policycoreutils/Default)
+    DEPENDS+= policycoreutils $(DEPENDS_$(2))
+    TITLE+= $(2)
+    ALTERNATIVES:=$(ALTS_$(2))
+  endef
+
+  define Package/$(1)/description
+Policycoreutils is a collection of policy utilities
+(originally the "core" set of utilities needed to use
+SELinux, although it has grown a bit over time).
+
+This package provides the $(2) utility.
+  endef
+endef
+
+$(foreach a,$(LIBEXEC_UTILS) $(SBIN_UTILS) $(USR_BIN_UTILS) $(USR_SBIN_UTILS),$(eval $(call GenUtilPkg,policycoreutils-$(a),$(a))))
+
+define Package/policycoreutils/install
+	$(INSTALL_DIR) $(1)/etc
+	$(INSTALL_CONF) $(PKG_INSTALL_DIR)/etc/sestatus.conf $(1)/etc
+ifdef CONFIG_BUSYBOX_CONFIG_PAM
+	$(INSTALL_DIR) $(1)/etc/pam.d
+	$(INSTALL_CONF) $(PKG_INSTALL_DIR)/etc/pam.d/run_init $(1)/etc/pam.d
+	$(INSTALL_CONF) $(PKG_INSTALL_DIR)/etc/pam.d/newrole $(1)/etc/pam.d
+endif
+endef
+
+define BuildUtil
+  define Package/$(1)/install
+	$(INSTALL_DIR) $$(1)$(2)
+	$(INSTALL_BIN) $$(PKG_INSTALL_DIR)$(2)/$(3) $$(1)$(2)/$(if $(ALTS_$(3)),policycoreutils-$(3),$(3))
+  endef
+
+  $$(eval $$(call BuildPackage,$(1)))
+endef
+
+$(eval $(call BuildPackage,policycoreutils))
+$(foreach a,$(SBIN_UTILS),$(eval $(call BuildUtil,policycoreutils-$(a),/sbin,$(a))))
+$(foreach a,$(USR_BIN_UTILS),$(eval $(call BuildUtil,policycoreutils-$(a),/usr/bin,$(a))))
+$(foreach a,$(USR_SBIN_UTILS),$(eval $(call BuildUtil,policycoreutils-$(a),/usr/sbin,$(a))))
+$(foreach a,$(LIBEXEC_UTILS),$(eval $(call BuildUtil,policycoreutils-$(a),/usr/libexec/selinux/hll,$(a))))
+$(eval $(call HostBuild))
diff --git a/package/utils/policycoreutils/patches/001-fix-hostbuild.patch b/package/utils/policycoreutils/patches/001-fix-hostbuild.patch
new file mode 100644
index 0000000..9c7da51
--- /dev/null
+++ b/package/utils/policycoreutils/patches/001-fix-hostbuild.patch
@@ -0,0 +1,12 @@
+diff --git a/sestatus/Makefile b/sestatus/Makefile
+index 3dbb792..d5d80cb 100644
+--- a/sestatus/Makefile
++++ b/sestatus/Makefile
+@@ -22,6 +22,7 @@ install: all
+ 	# Some tools hard code /usr/sbin/sestatus ; add a compatibility symlink
+ 	# install will overwrite a symlink, so create the symlink before calling
+ 	# install to allow distributions with BINDIR == SBINDIR
++	rm -f $(DESTDIR)$(SBINDIR)/sestatus
+ 	ln -sf --relative $(DESTDIR)$(BINDIR)/sestatus $(DESTDIR)$(SBINDIR)
+ 	install -m 755 sestatus $(DESTDIR)$(BINDIR)
+ 	install -m 644 sestatus.8 $(DESTDIR)$(MANDIR)/man8
diff --git a/package/utils/px5g-mbedtls/Makefile b/package/utils/px5g-mbedtls/Makefile
new file mode 100644
index 0000000..6addbba
--- /dev/null
+++ b/package/utils/px5g-mbedtls/Makefile
@@ -0,0 +1,69 @@
+#
+# Copyright (C) 2010-2015 Jo-Philipp Wich <jo@mein.io>
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=px5g-mbedtls
+PKG_RELEASE:=11
+PKG_LICENSE:=LGPL-2.1
+
+PKG_BUILD_FLAGS:=no-mips16
+
+PKG_MAINTAINER:=Jo-Philipp Wich <jo@mein.io>
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/px5g-mbedtls
+  SECTION:=utils
+  CATEGORY:=Utilities
+  SUBMENU:=Encryption
+  TITLE:=X.509 certificate generator (using mbedtls)
+  DEPENDS:=+libmbedtls
+  PROVIDES:=px5g
+  VARIANT:=mbedtls
+endef
+
+define Package/px5g-mbedtls/description
+ Px5g is a tiny standalone X.509 certificate generator.
+ It suitable to create key files and certificates in DER
+ and PEM format for use with stunnel, uhttpd and others.
+endef
+
+define Package/px5g-standalone
+  SECTION:=utils
+  CATEGORY:=Utilities
+  SUBMENU:=Encryption
+  TITLE:=X.509 certificate generator (standalone)
+  VARIANT:=standalone
+endef
+Package/px5g-standalone/description = $(Package/px5g-mbedtls/description)
+
+define Build/Prepare
+	mkdir -p $(PKG_BUILD_DIR)
+endef
+
+TARGET_LDFLAGS += -lmbedtls -lmbedx509 -lmbedcrypto
+
+ifeq ($(BUILD_VARIANT),standalone)
+  TARGET_LDFLAGS := -Wl,-Bstatic $(TARGET_LDFLAGS) -Wl,-Bdynamic
+endif
+
+TARGET_CFLAGS += -Wl,--gc-sections -Wall -Werror
+
+define Build/Compile
+	$(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) -o $(PKG_BUILD_DIR)/px5g px5g-mbedtls.c $(TARGET_LDFLAGS)
+endef
+
+define Package/px5g-mbedtls/install
+	$(INSTALL_DIR) $(1)/usr/sbin
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/px5g $(1)/usr/sbin/px5g
+endef
+
+Package/px5g-standalone/install = $(Package/px5g-mbedtls/install)
+
+$(eval $(call BuildPackage,px5g-mbedtls))
+$(eval $(call BuildPackage,px5g-standalone))
diff --git a/package/utils/px5g-mbedtls/px5g-mbedtls.c b/package/utils/px5g-mbedtls/px5g-mbedtls.c
new file mode 100644
index 0000000..63f54bd
--- /dev/null
+++ b/package/utils/px5g-mbedtls/px5g-mbedtls.c
@@ -0,0 +1,412 @@
+/*
+ * px5g - Embedded x509 key and certificate generator based on PolarSSL
+ *
+ *   Copyright (C) 2009 Steven Barth <steven@midlink.org>
+ *   Copyright (C) 2014 Felix Fietkau <nbd@nbd.name>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License, version 2.1 as published by the Free Software Foundation.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ *  MA  02110-1301  USA
+ */
+
+#include <sys/types.h>
+#include <sys/random.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <limits.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <errno.h>
+
+#include <mbedtls/bignum.h>
+#include <mbedtls/entropy.h>
+#include <mbedtls/x509_crt.h>
+#include <mbedtls/ecp.h>
+#include <mbedtls/rsa.h>
+#include <mbedtls/pk.h>
+#include <mbedtls/asn1.h>
+#include <mbedtls/oid.h>
+
+#define SET_OID(x, oid) \
+	do { x.len = MBEDTLS_OID_SIZE(oid); x.p = (unsigned char *) oid; } while (0)
+
+#define PX5G_VERSION "0.3"
+#define PX5G_COPY "Copyright (c) 2009 Steven Barth <steven@midlink.org>"
+#define PX5G_LICENSE "Licensed under the GNU Lesser General Public License v2.1"
+
+static char buf[16384];
+
+static int _urandom(void *ctx, unsigned char *out, size_t len)
+{
+	ssize_t ret;
+
+	ret = getrandom(out, len, 0);
+	if (ret < 0 || (size_t)ret != len)
+		return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
+
+	return 0;
+}
+
+static void write_file(const char *path, size_t len, bool pem, bool cert)
+{
+	mode_t mode = S_IRUSR | S_IWUSR;
+	const char *buf_start = buf;
+	int fd = STDERR_FILENO;
+	ssize_t written;
+	int err;
+
+	if (!pem)
+		buf_start += sizeof(buf) - len;
+
+	if (!len) {
+		fprintf(stderr, "No data to write\n");
+		exit(1);
+	}
+	
+	if (cert)
+		mode |= S_IRGRP | S_IROTH;
+
+	if (path)
+		fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
+
+	if (fd < 0) {
+		fprintf(stderr, "error: I/O error\n");
+		exit(1);
+	}
+
+	written = write(fd, buf_start, len);
+	if (written != len) {
+		fprintf(stderr, "writing key failed with: %s\n", strerror(errno));
+		exit(1);
+	}
+	err = fsync(fd);
+	if (err < 0) {
+		fprintf(stderr, "syncing key failed with: %s\n", strerror(errno));
+		exit(1);
+	}
+	if (path)
+		close(fd);
+}
+
+static mbedtls_ecp_group_id ecp_curve(const char *name)
+{
+	const mbedtls_ecp_curve_info *curve_info;
+
+	if (!strcmp(name, "P-256"))
+		return MBEDTLS_ECP_DP_SECP256R1;
+	else if (!strcmp(name, "P-384"))
+		return MBEDTLS_ECP_DP_SECP384R1;
+	else if (!strcmp(name, "P-521"))
+		return MBEDTLS_ECP_DP_SECP521R1;
+	curve_info = mbedtls_ecp_curve_info_from_name(name);
+	if (curve_info == NULL)
+		return MBEDTLS_ECP_DP_NONE;
+	else
+		return curve_info->grp_id;
+}
+
+static void write_key(mbedtls_pk_context *key, const char *path, bool pem)
+{
+	int len = 0;
+
+	if (pem) {
+		if (mbedtls_pk_write_key_pem(key, (void *) buf, sizeof(buf)) == 0)
+			len = strlen(buf);
+	} else {
+		len = mbedtls_pk_write_key_der(key, (void *) buf, sizeof(buf));
+		if (len < 0)
+			len = 0;
+	}
+
+	write_file(path, len, pem, false);
+}
+
+static void gen_key(mbedtls_pk_context *key, bool rsa, int ksize, int exp,
+		    mbedtls_ecp_group_id curve, bool pem)
+{
+	mbedtls_pk_init(key);
+	if (rsa) {
+		fprintf(stderr, "Generating RSA private key, %i bit long modulus\n", ksize);
+		mbedtls_pk_setup(key, mbedtls_pk_info_from_type(MBEDTLS_PK_RSA));
+		if (!mbedtls_rsa_gen_key(mbedtls_pk_rsa(*key), _urandom, NULL, ksize, exp))
+			return;
+	} else {
+		fprintf(stderr, "Generating EC private key\n");
+		mbedtls_pk_setup(key, mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY));
+		if (!mbedtls_ecp_gen_key(curve, mbedtls_pk_ec(*key), _urandom, NULL))
+			return;
+	}
+	fprintf(stderr, "error: key generation failed\n");
+	exit(1);
+}
+
+int dokey(bool rsa, char **arg)
+{
+	mbedtls_pk_context key;
+	unsigned int ksize = 512;
+	int exp = 65537;
+	char *path = NULL;
+	bool pem = true;
+	mbedtls_ecp_group_id curve = MBEDTLS_ECP_DP_SECP256R1;
+
+	while (*arg && **arg == '-') {
+		if (!strcmp(*arg, "-out") && arg[1]) {
+			path = arg[1];
+			arg++;
+		} else if (!strcmp(*arg, "-3")) {
+			exp = 3;
+		} else if (!strcmp(*arg, "-der")) {
+			pem = false;
+		}
+		arg++;
+	}
+
+	if (*arg && rsa) {
+		ksize = (unsigned int)atoi(*arg);
+	} else if (*arg) {
+		curve = ecp_curve((const char *)*arg);
+		if (curve == MBEDTLS_ECP_DP_NONE) {
+			fprintf(stderr, "error: invalid curve name: %s\n", *arg);
+			return 1;
+		}
+	}
+
+	gen_key(&key, rsa, ksize, exp, curve, pem);
+	write_key(&key, path, pem);
+
+	mbedtls_pk_free(&key);
+
+	return 0;
+}
+
+int selfsigned(char **arg)
+{
+	mbedtls_pk_context key;
+	mbedtls_x509write_cert cert;
+	mbedtls_mpi serial;
+	mbedtls_x509_san_list *san_list = NULL, *san_prev = NULL, *san_cur = NULL;
+	/*support
+	- MBEDTLS_X509_SAN_DNS_NAME
+	- MBEDTLS_X509_SAN_IP_ADDRESS
+	- MBEDTLS_X509_SAN_RFC822_NAME
+	- MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER
+	*/
+	mbedtls_asn1_sequence *eku = NULL, *ext_key_usage = NULL;
+	char *sanval, *santype;
+	uint8_t ipaddr[16] = { 0 };
+
+	char *subject = "";
+	unsigned int ksize = 512;
+	int exp = 65537;
+	unsigned int days = 30;
+	char *keypath = NULL, *certpath = NULL;
+	bool pem = true;
+	time_t from = time(NULL), to;
+	char fstr[20], tstr[20], sstr[17];
+	int len;
+	bool rsa = true;
+	mbedtls_ecp_group_id curve = MBEDTLS_ECP_DP_SECP256R1;
+
+	while (*arg && **arg == '-') {
+		if (!strcmp(*arg, "-der")) {
+			pem = false;
+		} else if (!strcmp(*arg, "-newkey") && arg[1]) {
+			if (!strncmp(arg[1], "rsa:", 4)) {
+				rsa = true;
+				ksize = (unsigned int)atoi(arg[1] + 4);
+			} else if (!strcmp(arg[1], "ec")) {
+				rsa = false;
+			} else {
+				fprintf(stderr, "error: invalid algorithm\n");
+				return 1;
+			}
+			arg++;
+		} else if (!strcmp(*arg, "-days") && arg[1]) {
+			days = (unsigned int)atoi(arg[1]);
+			arg++;
+		} else if (!strcmp(*arg, "-pkeyopt") && arg[1]) {
+			if (strncmp(arg[1], "ec_paramgen_curve:", 18)) {
+				fprintf(stderr, "error: invalid pkey option: %s\n", arg[1]);
+				return 1;
+			}
+			curve = ecp_curve((const char *)(arg[1] + 18));
+			if (curve == MBEDTLS_ECP_DP_NONE) {
+				fprintf(stderr, "error: invalid curve name: %s\n", arg[1] + 18);
+				return 1;
+			}
+			arg++;
+		} else if (!strcmp(*arg, "-keyout") && arg[1]) {
+			keypath = arg[1];
+			arg++;
+		} else if (!strcmp(*arg, "-out") && arg[1]) {
+			certpath = arg[1];
+			arg++;
+		} else if (!strcmp(*arg, "-subj") && arg[1]) {
+			if (arg[1][0] != '/' || strchr(arg[1], ';')) {
+				fprintf(stderr, "error: invalid subject");
+				return 1;
+			}
+			subject = calloc(strlen(arg[1]) + 1, 1);
+			char *oldc = arg[1] + 1, *newc = subject, *delim;
+			do {
+				delim = strchr(oldc, '=');
+				if (!delim) {
+					fprintf(stderr, "error: invalid subject");
+					return 1;
+				}
+				memcpy(newc, oldc, delim - oldc + 1);
+				newc += delim - oldc + 1;
+				oldc = delim + 1;
+
+				delim = strchr(oldc, '/');
+				if (!delim) {
+					delim = arg[1] + strlen(arg[1]);
+				}
+				memcpy(newc, oldc, delim - oldc);
+				newc += delim - oldc;
+				*newc++ = ',';
+				oldc = delim + 1;
+			} while(*delim);
+			arg++;
+		} else if (!strcmp(*arg, "-addext") && arg[1]) {
+			mbedtls_asn1_sequence **tail = &eku;
+			if (!strncmp(arg[1], "extendedKeyUsage=", strlen("extendedKeyUsage="))) {
+				ext_key_usage = calloc(1, sizeof(mbedtls_asn1_sequence));
+				ext_key_usage->buf.tag = MBEDTLS_ASN1_OID;
+				if (!strncmp(arg[1] + strlen("extendedKeyUsage="), "serverAuth", strlen("serverAuth"))) {
+					SET_OID(ext_key_usage->buf, MBEDTLS_OID_SERVER_AUTH);
+				} else if (!strncmp(arg[1] + strlen("extendedKeyUsage="), "any", strlen("any"))) {
+					SET_OID(ext_key_usage->buf, MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE);
+				} // there are other extendedKeyUsage OIDs but none conceivably useful here
+				*tail = ext_key_usage;
+				tail = &ext_key_usage->next;
+				arg++;
+			} else if (!strncmp(arg[1], "subjectAltName=", strlen("subjectAltName=")) && strchr(arg[1], ':') != NULL) {
+				santype = strchr(arg[1], '=') + 1;
+				sanval = strchr(arg[1], ':') + 1;
+				//build sAN list
+				san_cur = calloc(1, sizeof(mbedtls_x509_san_list));
+				san_cur->next = NULL;
+				if (!strncmp(santype, "DNS:", strlen("DNS:"))) {
+					san_cur->node.type = MBEDTLS_X509_SAN_DNS_NAME;
+					san_cur->node.san.unstructured_name.p = (unsigned char *) sanval;
+					san_cur->node.san.unstructured_name.len = strlen(sanval);
+				} else if (!strncmp(santype, "EMAIL:", strlen("EMAIL:"))) {
+					san_cur->node.type = MBEDTLS_X509_SAN_RFC822_NAME;
+					san_cur->node.san.unstructured_name.p = (unsigned char *) sanval;
+					san_cur->node.san.unstructured_name.len = strlen(sanval);
+				} else if (!strncmp(santype, "IP:", strlen("IP:"))) {
+					san_cur->node.type = MBEDTLS_X509_SAN_IP_ADDRESS;
+					mbedtls_x509_crt_parse_cn_inet_pton(sanval, ipaddr);
+					san_cur->node.san.unstructured_name.p = (unsigned char *) ipaddr;
+					san_cur->node.san.unstructured_name.len = sizeof(ipaddr);
+				} else if (!strncmp(santype, "URI:", strlen("URI:"))) {
+					san_cur->node.type = MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER;
+					san_cur->node.san.unstructured_name.p = (unsigned char *) sanval;
+					san_cur->node.san.unstructured_name.len = strlen(sanval);
+				}
+				else fprintf(stderr, "No match to subjectAltName content type.\n");
+			arg++;
+			}
+		}
+		arg++;
+
+		//set the pointers in our san_list linked list
+		if (san_prev == NULL) {
+			san_list = san_cur;
+		} else {
+			san_prev->next = san_cur;
+		}
+		san_prev = san_cur;
+	}
+	gen_key(&key, rsa, ksize, exp, curve, pem);
+
+	if (keypath)
+		write_key(&key, keypath, pem);
+
+	from = (from < 1000000000) ? 1000000000 : from;
+	strftime(fstr, sizeof(fstr), "%Y%m%d%H%M%S", gmtime(&from));
+	to = from + 60 * 60 * 24 * days;
+	if (to < from)
+		to = INT_MAX;
+	strftime(tstr, sizeof(tstr), "%Y%m%d%H%M%S", gmtime(&to));
+
+	fprintf(stderr, "Generating selfsigned certificate with subject '%s'"
+			" and validity %s-%s\n", subject, fstr, tstr);
+
+	mbedtls_x509write_crt_init(&cert);
+	mbedtls_x509write_crt_set_md_alg(&cert, MBEDTLS_MD_SHA256);
+	mbedtls_x509write_crt_set_issuer_key(&cert, &key);
+	mbedtls_x509write_crt_set_subject_key(&cert, &key);
+	mbedtls_x509write_crt_set_subject_name(&cert, subject);
+	mbedtls_x509write_crt_set_issuer_name(&cert, subject);
+	mbedtls_x509write_crt_set_validity(&cert, fstr, tstr);
+	mbedtls_x509write_crt_set_basic_constraints(&cert, 0, -1);
+	mbedtls_x509write_crt_set_subject_key_identifier(&cert);
+	mbedtls_x509write_crt_set_authority_key_identifier(&cert);
+	mbedtls_x509write_crt_set_subject_alternative_name(&cert, san_list);
+	mbedtls_x509write_crt_set_ext_key_usage(&cert, ext_key_usage);
+
+	_urandom(NULL, (void *) buf, 8);
+	for (len = 0; len < 8; len++)
+		sprintf(sstr + len*2, "%02x", (unsigned char) buf[len]);
+
+	mbedtls_mpi_init(&serial);
+	mbedtls_mpi_read_string(&serial, 16, sstr);
+	mbedtls_x509write_crt_set_serial(&cert, &serial);
+
+	if (pem) {
+		if (mbedtls_x509write_crt_pem(&cert, (void *) buf, sizeof(buf), _urandom, NULL) < 0) {
+			fprintf(stderr, "Failed to generate certificate\n");
+			return 1;
+		}
+
+		len = strlen(buf);
+	} else {
+		len = mbedtls_x509write_crt_der(&cert, (void *) buf, sizeof(buf), _urandom, NULL);
+		if (len < 0) {
+			fprintf(stderr, "Failed to generate certificate: %d\n", len);
+			return 1;
+		}
+	}
+	write_file(certpath, len, pem, true);
+
+	mbedtls_x509write_crt_free(&cert);
+	mbedtls_mpi_free(&serial);
+	mbedtls_pk_free(&key);
+
+	return 0;
+}
+
+int main(int argc, char *argv[])
+{
+	if (!argv[1]) {
+		//Usage
+	} else if (!strcmp(argv[1], "eckey")) {
+		return dokey(false, argv+2);
+	} else if (!strcmp(argv[1], "rsakey")) {
+		return dokey(true, argv+2);
+	} else if (!strcmp(argv[1], "selfsigned")) {
+		return selfsigned(argv+2);
+	}
+
+	fprintf(stderr,
+		"PX5G X.509 Certificate Generator Utility v" PX5G_VERSION "\n" PX5G_COPY
+		"\nbased on PolarSSL by Christophe Devine and Paul Bakker\n\n");
+	fprintf(stderr, "Usage: %s [eckey|rsakey|selfsigned]\n", *argv);
+	return 1;
+}
diff --git a/package/utils/px5g-wolfssl/Makefile b/package/utils/px5g-wolfssl/Makefile
new file mode 100644
index 0000000..ba208f6
--- /dev/null
+++ b/package/utils/px5g-wolfssl/Makefile
@@ -0,0 +1,50 @@
+# Copyright (C) 2020 Paul Spooren <mail@aparcar.org>
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=px5g-wolfssl
+PKG_RELEASE:=9
+PKG_LICENSE:=GPL-2.0-or-later
+
+PKG_BUILD_FLAGS:=no-mips16
+
+PKG_MAINTAINER:=Paul Spooren <mail@aparcar.org>
+
+PKG_CONFIG_DEPENDS:=CONFIG_WOLFSSL_ALT_NAMES
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/px5g-wolfssl
+  SECTION:=utils
+  CATEGORY:=Utilities
+  SUBMENU:=Encryption
+  TITLE:=X.509 certificate generator (using WolfSSL)
+  DEPENDS:=+libwolfssl
+  PROVIDES:=px5g
+  VARIANT:=wolfssl
+endef
+
+define Package/px5g-wolfssl/description
+ Px5g is a tiny X.509 certificate generator.
+ It suitable to create key files and certificates in DER
+ and PEM format for use with stunnel, uhttpd and others.
+endef
+
+TARGET_LDFLAGS += -lwolfssl
+
+
+TARGET_CFLAGS += -Wl,--gc-sections
+
+define Build/Compile
+	$(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) \
+		-o $(PKG_BUILD_DIR)/px5g px5g-wolfssl.c $(TARGET_LDFLAGS)
+endef
+
+define Package/px5g-wolfssl/install
+	$(INSTALL_DIR) $(1)/usr/sbin
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/px5g $(1)/usr/sbin/px5g
+endef
+
+$(eval $(call BuildPackage,px5g-wolfssl))
diff --git a/package/utils/px5g-wolfssl/px5g-wolfssl.c b/package/utils/px5g-wolfssl/px5g-wolfssl.c
new file mode 100644
index 0000000..755d370
--- /dev/null
+++ b/package/utils/px5g-wolfssl/px5g-wolfssl.c
@@ -0,0 +1,385 @@
+// Copyright 2020 Paul Spooren <mail@aparcar.org>
+//
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#define _GNU_SOURCE
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <wolfssl/options.h>
+#include <wolfssl/wolfcrypt/asn.h>
+#include <wolfssl/wolfcrypt/asn_public.h>
+#include <wolfssl/wolfcrypt/ecc.h>
+#include <wolfssl/wolfcrypt/error-crypt.h>
+#include <wolfssl/wolfcrypt/rsa.h>
+#include <wolfssl/wolfcrypt/settings.h>
+
+#define HEAP_HINT NULL
+#define FOURK_SZ 4096
+#define WOLFSSL_MIN_RSA_BITS 2048
+
+enum {
+  EC_KEY_TYPE = 0,
+  RSA_KEY_TYPE = 1,
+};
+
+int write_file(byte *buf, int bufSz, char *path, bool cert) {
+  mode_t mode = S_IRUSR | S_IWUSR;
+  ssize_t written;
+  int err;
+  int fd;
+
+  if (cert)
+    mode |= S_IRGRP | S_IROTH;
+
+  if (path) {
+    fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
+    if (fd < 0) {
+      perror("Error opening file");
+      exit(1);
+    }
+  } else {
+    fd = STDERR_FILENO;
+  }
+  written = write(fd, buf, bufSz);
+  if (written != bufSz) {
+    perror("Error write file");
+    exit(1);
+  }
+  err = fsync(fd);
+  if (err < 0) {
+    perror("Error fsync file");
+    exit(1);
+  }
+  if (path) {
+    close(fd);
+  }
+  return 0;
+}
+
+int write_key(ecc_key *ecKey, RsaKey *rsaKey, int type, int keySz, char *fName,
+              bool write_pem) {
+  int ret;
+  byte der[FOURK_SZ] = {};
+  byte pem[FOURK_SZ] = {};
+  int derSz, pemSz;
+  if (type == EC_KEY_TYPE) {
+    ret = wc_EccKeyToDer(ecKey, der, sizeof(der));
+  } else {
+    ret = wc_RsaKeyToDer(rsaKey, der, sizeof(der));
+  }
+  if (ret <= 0) {
+    fprintf(stderr, "Key To DER failed: %d\n", ret);
+  }
+  derSz = ret;
+
+  if (write_pem) {
+    if (type == EC_KEY_TYPE) {
+      ret = wc_DerToPem(der, derSz, pem, sizeof(pem), ECC_PRIVATEKEY_TYPE);
+    } else {
+      ret = wc_DerToPem(der, derSz, pem, sizeof(pem), PRIVATEKEY_TYPE);
+    }
+    if (ret <= 0) {
+      fprintf(stderr, "DER to PEM failed: %d\n", ret);
+    }
+    pemSz = ret;
+    ret = write_file(pem, pemSz, fName, false);
+  } else {
+    ret = write_file(der, derSz, fName, false);
+  }
+  return ret;
+}
+
+int gen_key(WC_RNG *rng, ecc_key *ecKey, RsaKey *rsaKey, int type, int keySz,
+            long exp, int curve) {
+  int ret;
+
+  if (type == EC_KEY_TYPE) {
+    ret = wc_ecc_init(ecKey);
+    (void)rsaKey;
+  } else {
+    ret = wc_InitRsaKey(rsaKey, NULL);
+    (void)ecKey;
+  }
+  if (ret != 0) {
+    fprintf(stderr, "Key initialization failed: %d\n", ret);
+    return ret;
+  }
+
+  if (type == EC_KEY_TYPE) {
+    fprintf(stderr, "Generating EC private key\n");
+    ret = wc_ecc_make_key_ex(rng, 32, ecKey, curve);
+  } else {
+    fprintf(stderr, "Generating RSA private key, %i bit long modulus\n", keySz);
+    ret = wc_MakeRsaKey(rsaKey, keySz, WC_RSA_EXPONENT, rng);
+  }
+  if (ret != 0) {
+    fprintf(stderr, "Key generation failed: %d\n", ret);
+  }
+  return ret;
+}
+
+int selfsigned(WC_RNG *rng, char **arg) {
+  ecc_key ecKey;
+  RsaKey rsaKey;
+  int ret;
+  char *subject = "";
+  int keySz = WOLFSSL_MIN_RSA_BITS;
+  int type = EC_KEY_TYPE;
+  int exp = WC_RSA_EXPONENT;
+  int curve = ECC_SECP256R1;
+  unsigned int days = 3653; // 10 years
+  char *keypath = NULL, *certpath = NULL;
+  char fstr[20], tstr[20];
+  bool pem = true;
+  Cert newCert;
+#ifdef __USE_TIME_BITS64
+  time_t to, from = time(NULL);
+#else
+  unsigned long to, from = time(NULL);
+#endif
+  byte derBuf[FOURK_SZ] = {};
+  byte pemBuf[FOURK_SZ] = {};
+  int pemSz = -1;
+  int derSz = -1;
+  char *key, *val, *tmp;
+
+  ret = wc_InitCert(&newCert);
+  if (ret != 0) {
+    fprintf(stderr, "Init Cert failed: %d\n", ret);
+    return ret;
+  }
+  newCert.isCA = 0;
+
+  while (*arg && **arg == '-') {
+    if (!strcmp(*arg, "-der")) {
+      pem = false;
+    } else if (!strcmp(*arg, "-newkey") && arg[1]) {
+      if (!strncmp(arg[1], "rsa:", 4)) {
+        type = RSA_KEY_TYPE;
+        keySz = atoi(arg[1] + 4);
+      } else if (!strcmp(arg[1], "ec")) {
+        type = EC_KEY_TYPE;
+      } else {
+        fprintf(stderr, "error: invalid algorithm\n");
+        return 1;
+      }
+      arg++;
+    } else if (!strcmp(*arg, "-days") && arg[1]) {
+      days = (unsigned int)atoi(arg[1]);
+      arg++;
+    } else if (!strcmp(*arg, "-pkeyopt") && arg[1]) {
+      if (strncmp(arg[1], "ec_paramgen_curve:", 18)) {
+        fprintf(stderr, "error: invalid pkey option: %s\n", arg[1]);
+        return 1;
+      }
+      if (!strcmp(arg[1] + 18, "P-256")) {
+        curve = ECC_SECP256R1;
+      } else if (!strcmp(arg[1] + 18, "P-384")) {
+        curve = ECC_SECP384R1;
+      } else if (!strcmp(arg[1] + 18, "P-521")) {
+        curve = ECC_SECP521R1;
+      } else {
+        fprintf(stderr, "error: invalid curve name: %s\n", arg[1] + 18);
+        return 1;
+      }
+      arg++;
+    } else if (!strcmp(*arg, "-keyout") && arg[1]) {
+      keypath = arg[1];
+      arg++;
+    } else if (!strcmp(*arg, "-out") && arg[1]) {
+      certpath = arg[1];
+      arg++;
+    } else if (!strcmp(*arg, "-subj") && arg[1]) {
+      subject = strdupa(arg[1]);
+      key = arg[1];
+      do {
+        tmp = strchr(key, '/');
+        if (tmp)
+          *tmp = '\0';
+
+        val = strchr(key, '=');
+        if (val) {
+          *val = '\0';
+          ++val;
+
+          if (!strcmp(key, "C"))
+            strncpy(newCert.subject.country, val, CTC_NAME_SIZE);
+          else if (!strcmp(key, "ST"))
+            strncpy(newCert.subject.state, val, CTC_NAME_SIZE);
+          else if (!strcmp(key, "L"))
+            strncpy(newCert.subject.locality, val, CTC_NAME_SIZE);
+          else if (!strcmp(key, "O"))
+            strncpy(newCert.subject.org, val, CTC_NAME_SIZE);
+          else if (!strcmp(key, "OU"))
+            strncpy(newCert.subject.unit, val, CTC_NAME_SIZE);
+          else if (!strcmp(key, "CN")) {
+            strncpy(newCert.subject.commonName, val, CTC_NAME_SIZE);
+
+#ifdef WOLFSSL_ALT_NAMES
+            if(strlen(val) + 2 > 256) {
+              fprintf(stderr, "error: CN is too long: %s\n", val);
+              return 1;
+            }
+
+            newCert.altNames[0] = 0x30; //Sequence with one element
+            newCert.altNames[1] = strlen(val) + 2; // Length of entire sequence
+            newCert.altNames[2] = 0x82; //8 - String, 2 - DNS Name
+            newCert.altNames[3] = strlen(val); //DNS Name length
+            memcpy(newCert.altNames + 4, val, strlen(val)); //DNS Name
+            newCert.altNamesSz = strlen(val) + 4;
+#endif
+          }
+          else if (!strcmp(key, "EMAIL"))
+            strncpy(newCert.subject.email, val, CTC_NAME_SIZE);
+          else
+            printf("warning: unknown attribute %s=%s\n", key, val);
+        }
+      } while (tmp && (key = ++tmp));
+    }
+    arg++;
+  }
+  newCert.daysValid = days;
+
+  newCert.keyUsage = KEYUSE_DIGITAL_SIG | KEYUSE_CONTENT_COMMIT | KEYUSE_KEY_ENCIPHER;
+  newCert.extKeyUsage = EXTKEYUSE_SERVER_AUTH;
+
+  gen_key(rng, &ecKey, &rsaKey, type, keySz, exp, curve);
+  write_key(&ecKey, &rsaKey, type, keySz, keypath, pem);
+
+  from = (from < 1000000000) ? 1000000000 : from;
+  strftime(fstr, sizeof(fstr), "%Y%m%d%H%M%S", gmtime(&from));
+  to = from + 60 * 60 * 24 * days;
+  if (to < from)
+    to = INT_MAX;
+  strftime(tstr, sizeof(tstr), "%Y%m%d%H%M%S", gmtime(&to));
+
+  fprintf(stderr,
+          "Generating selfsigned certificate with subject '%s'"
+          " and validity %s-%s\n",
+          subject, fstr, tstr);
+
+  if (type == EC_KEY_TYPE) {
+    newCert.sigType = CTC_SHA256wECDSA;
+    ret = wc_MakeCert(&newCert, derBuf, sizeof(derBuf), NULL, &ecKey, rng);
+  } else {
+    newCert.sigType = CTC_SHA256wRSA;
+    ret = wc_MakeCert(&newCert, derBuf, sizeof(derBuf), &rsaKey, NULL, rng);
+  }
+  if (ret <= 0) {
+    fprintf(stderr, "Make Cert failed: %d\n", ret);
+    return ret;
+  }
+
+  if (type == EC_KEY_TYPE) {
+    ret = wc_SignCert(newCert.bodySz, newCert.sigType, derBuf, sizeof(derBuf),
+                      NULL, &ecKey, rng);
+  } else {
+    ret = wc_SignCert(newCert.bodySz, newCert.sigType, derBuf, sizeof(derBuf),
+                      &rsaKey, NULL, rng);
+  }
+  if (ret <= 0) {
+    fprintf(stderr, "Sign Cert failed: %d\n", ret);
+    return ret;
+  }
+  derSz = ret;
+
+  ret = wc_DerToPem(derBuf, derSz, pemBuf, sizeof(pemBuf), CERT_TYPE);
+  if (ret <= 0) {
+    fprintf(stderr, "DER to PEM failed: %d\n", ret);
+    return ret;
+  }
+  pemSz = ret;
+
+  ret = write_file(pemBuf, pemSz, certpath, true);
+  if (ret != 0) {
+    fprintf(stderr, "Write Cert failed: %d\n", ret);
+    return ret;
+  }
+
+  if (type == EC_KEY_TYPE) {
+    wc_ecc_free(&ecKey);
+  } else {
+    wc_FreeRsaKey(&rsaKey);
+  }
+  return 0;
+}
+
+int dokey(WC_RNG *rng, int type, char **arg) {
+  ecc_key ecKey;
+  RsaKey rsaKey;
+  int ret;
+  int curve = ECC_SECP256R1;
+  int keySz = WOLFSSL_MIN_RSA_BITS;
+  int exp = WC_RSA_EXPONENT;
+  char *path = NULL;
+  bool pem = true;
+
+  while (*arg && **arg == '-') {
+    if (!strcmp(*arg, "-out") && arg[1]) {
+      path = arg[1];
+      arg++;
+    } else if (!strcmp(*arg, "-3")) {
+      exp = 3;
+    } else if (!strcmp(*arg, "-der")) {
+      pem = false;
+    }
+    arg++;
+  }
+
+  if (*arg && type == RSA_KEY_TYPE) {
+    keySz = atoi(*arg);
+  } else if (*arg) {
+    if (!strcmp(*arg, "P-256")) {
+      curve = ECC_SECP256R1;
+    } else if (!strcmp(*arg, "P-384")) {
+      curve = ECC_SECP384R1;
+    } else if (!strcmp(*arg, "P-521")) {
+      curve = ECC_SECP521R1;
+    } else {
+      fprintf(stderr, "Invalid Curve Name: %s\n", *arg);
+      return 1;
+    }
+  }
+
+  ret = gen_key(rng, &ecKey, &rsaKey, type, keySz, exp, curve);
+  if (ret != 0)
+    return ret;
+
+  ret = write_key(&ecKey, &rsaKey, type, keySz, path, pem);
+
+  if (type == EC_KEY_TYPE) {
+    wc_ecc_free(&ecKey);
+  } else {
+    wc_FreeRsaKey(&rsaKey);
+  }
+  return ret;
+}
+
+int main(int argc, char *argv[]) {
+  int ret;
+  WC_RNG rng;
+  ret = wc_InitRng(&rng);
+  if (ret != 0) {
+    fprintf(stderr, "Init Rng failed: %d\n", ret);
+    return ret;
+  }
+
+  if (argv[1]) {
+    if (!strcmp(argv[1], "eckey"))
+      return dokey(&rng, EC_KEY_TYPE, argv + 2);
+
+    if (!strcmp(argv[1], "rsakey"))
+      return dokey(&rng, RSA_KEY_TYPE, argv + 2);
+
+    if (!strcmp(argv[1], "selfsigned"))
+      return selfsigned(&rng, argv + 2);
+  }
+
+  fprintf(stderr, "PX5G X.509 Certificate Generator Utilit using WolfSSL\n\n");
+  fprintf(stderr, "Usage: [eckey|rsakey|selfsigned]\n");
+  return 1;
+}
diff --git a/package/utils/ravpower-mcu/Makefile b/package/utils/ravpower-mcu/Makefile
new file mode 100644
index 0000000..8139e1b
--- /dev/null
+++ b/package/utils/ravpower-mcu/Makefile
@@ -0,0 +1,34 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=ravpower-mcu
+PKG_RELEASE:=2
+
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_URL=https://github.com/blocktrron/ravpower-mcu.git
+PKG_MIRROR_HASH:=683c04c85c6f973d3e9a0c9d0f77e2dde4e89ff0d40a28ad6682bc2550022b3c
+PKG_SOURCE_DATE:=2020-06-19
+PKG_SOURCE_VERSION:=1665d9e9212dcd118629a74fbe658841f81036f7
+PKG_MAINTAINER:=David Bauer <mail@david-bauer.net>
+PKG_LICENSE:=GPL-2.0-or-later
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/ravpower-mcu
+  SECTION:=utils
+  CATEGORY:=Utilities
+  TITLE:=Utility to control the RAVPower RP-WD009 PMIC
+  URL:=https://github.com/blocktrron/ravpower-mcu/
+endef
+
+define Build/Compile
+	$(MAKE) -C $(PKG_BUILD_DIR) \
+		CC="$(TARGET_CC)" \
+		CFLAGS="$(TARGET_CFLAGS) -Wall"
+endef
+
+define Package/ravpower-mcu/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/out/ravpower-mcu $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,ravpower-mcu))
diff --git a/package/utils/secilc/Makefile b/package/utils/secilc/Makefile
new file mode 100644
index 0000000..10547cf
--- /dev/null
+++ b/package/utils/secilc/Makefile
@@ -0,0 +1,65 @@
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=secilc
+PKG_VERSION:=3.5
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://github.com/SELinuxProject/selinux/releases/download/$(PKG_VERSION)
+PKG_HASH:=3eebc5a1f97847fa530cf90654b9f3b8f21a13c9ea3d07495325651580cd3373
+HOST_BUILD_DEPENDS:=libsepol/host
+
+PKG_MAINTAINER:=Dominick Grift <dominick.grift@defensec.nl>
+PKG_LICENSE:=BSD-2-Clause
+PKG_LICENSE_FILES:=COPYING
+
+include $(INCLUDE_DIR)/host-build.mk
+include $(INCLUDE_DIR)/nls.mk
+include $(INCLUDE_DIR)/package.mk
+
+HOST_LDFLAGS+=-Wl,-rpath=$(STAGING_DIR_HOSTPKG)/lib
+HOST_MAKE_FLAGS += \
+	DESTDIR=$(STAGING_DIR_HOSTPKG) \
+	PREFIX=
+
+define Package/secilc
+	SECTION:=utils
+	CATEGORY:=Utilities
+	TITLE:=SELinux Common Intermediate Language (CIL) Compiler
+	URL:=http://selinuxproject.org/page/Main_Page
+	DEPENDS:=+libsepol
+endef
+
+define Package/secilc/description
+	The SELinux CIL Compiler is a compiler that converts the CIL language as
+	described on the CIL design wiki into a kernel binary policy file.
+	Please see the CIL Design Wiki at:
+	http://github.com/SELinuxProject/cil/wiki/
+	for more information about the goals and features on the CIL language.
+endef
+
+define Build/Compile
+	$(call Build/Compile/Default,secilc)
+endef
+
+define Host/Compile
+	$(call Host/Compile/Default,secilc)
+endef
+
+define Host/Install
+	$(INSTALL_DIR) $(STAGING_DIR_HOSTPKG)/bin
+	$(INSTALL_BIN) $(HOST_BUILD_DIR)/secilc $(STAGING_DIR_HOSTPKG)/bin
+endef
+
+define Package/secilc/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/secilc $(1)/usr/bin
+endef
+
+$(eval $(call BuildPackage,secilc))
+$(eval $(call HostBuild))
diff --git a/package/utils/spidev_test/Makefile b/package/utils/spidev_test/Makefile
new file mode 100644
index 0000000..fef5c8f
--- /dev/null
+++ b/package/utils/spidev_test/Makefile
@@ -0,0 +1,60 @@
+#
+# Copyright (C) 2009 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=spidev-test
+PKG_RELEASE:=$(LINUX_VERSION)
+PKG_BUILD_DIR:=$(LINUX_DIR)/tools/spi-$(TARGET_DIR_NAME)
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/spidev-test
+  SECTION:=utils
+  CATEGORY:=Utilities
+  DEPENDS:=+kmod-spi-dev
+  TITLE:=SPI testing utility
+  VERSION:=$(LINUX_VERSION)-$(PKG_RELEASE)
+  URL:=http://www.kernel.org
+endef
+
+define Package/spidev-test/description
+  SPI testing utility.
+endef
+
+define Build/Prepare
+	# For SDK: Sources are copied by target/sdk/Makefile's
+	# USERSPACE_UTILS(_FILES)
+	$(CP) $(LINUX_DIR)/tools/spi/* $(PKG_BUILD_DIR)/
+endef
+
+MAKE_FLAGS = \
+	ARCH="$(LINUX_KARCH)" \
+	CROSS_COMPILE="$(TARGET_CROSS)" \
+	CC="$(TARGET_CC)" \
+	LD="$(TARGET_CROSS)ld" \
+	CFLAGS="$(TARGET_CFLAGS) $(TARGET_CPPFLAGS)" \
+	LDFLAGS="$(TARGET_LDFLAGS)" \
+	$(if $(findstring c,$(OPENWRT_VERBOSE)),V=1,V='') \
+	WERROR=0 \
+	prefix=/usr
+
+define Build/Compile
+	+$(MAKE_FLAGS) $(MAKE) $(PKG_JOBS) \
+		-C $(PKG_BUILD_DIR) \
+		-f Makefile \
+		--no-print-directory
+endef
+
+define Package/spidev-test/install
+	$(INSTALL_DIR) $(1)/sbin
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/spidev_test $(1)/sbin/
+endef
+
+$(eval $(call BuildPackage,spidev-test))
diff --git a/package/utils/ucode-mod-bpf/Makefile b/package/utils/ucode-mod-bpf/Makefile
new file mode 100644
index 0000000..a748b9d
--- /dev/null
+++ b/package/utils/ucode-mod-bpf/Makefile
@@ -0,0 +1,40 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=ucode-mod-bpf
+PKG_RELEASE:=1
+PKG_LICENSE:=ISC
+PKG_MAINTAINER:=Felix Fietkau <nbd@nbd.name>
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/nls.mk
+
+define Package/ucode-mod-bpf
+  SECTION:=utils
+  CATEGORY:=Utilities
+  TITLE:=ucode eBPF module
+  DEPENDS:=+libucode +libbpf
+endef
+
+define Package/ucode-mod-bpf/description
+The bpf plugin provides functionality for loading and interacting with
+eBPF modules.
+
+It allows loading full modules and pinned maps/programs and supports
+interacting with maps and attaching programs as tc classifiers.
+endef
+
+define Package/ucode-mod-bpf/install
+	$(INSTALL_DIR) $(1)/usr/lib/ucode
+	$(CP) $(PKG_BUILD_DIR)/bpf.so $(1)/usr/lib/ucode/
+endef
+
+define Build/Configure
+endef
+
+define Build/Compile
+	$(TARGET_CC) $(TARGET_CFLAGS) $(TARGET_LDFLAGS) $(FPIC) \
+		-Wall -ffunction-sections -Wl,--gc-sections -shared -Wl,--no-as-needed -lbpf \
+		-o $(PKG_BUILD_DIR)/bpf.so $(PKG_BUILD_DIR)/bpf.c
+endef
+
+$(eval $(call BuildPackage,ucode-mod-bpf))
diff --git a/package/utils/ucode-mod-bpf/src/bpf.c b/package/utils/ucode-mod-bpf/src/bpf.c
new file mode 100644
index 0000000..415215e
--- /dev/null
+++ b/package/utils/ucode-mod-bpf/src/bpf.c
@@ -0,0 +1,814 @@
+#include <sys/resource.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if.h>
+
+#include <stdint.h>
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include <bpf/bpf.h>
+#include <bpf/libbpf.h>
+
+#include "ucode/module.h"
+
+#define err_return_int(err, ...) do { set_error(err, __VA_ARGS__); return -1; } while(0)
+#define err_return(err, ...) do { set_error(err, __VA_ARGS__); return NULL; } while(0)
+#define TRUE ucv_boolean_new(true)
+
+static uc_resource_type_t *module_type, *map_type, *map_iter_type, *program_type;
+static uc_value_t *registry;
+static uc_vm_t *debug_vm;
+
+static struct {
+	int code;
+	char *msg;
+} last_error;
+
+struct uc_bpf_fd {
+	int fd;
+	bool close;
+};
+
+struct uc_bpf_map {
+	struct uc_bpf_fd fd; /* must be first */
+	unsigned int key_size, val_size;
+};
+
+struct uc_bpf_map_iter {
+	int fd;
+	unsigned int key_size;
+	bool has_next;
+	uint8_t key[];
+};
+
+__attribute__((format(printf, 2, 3))) static void
+set_error(int errcode, const char *fmt, ...)
+{
+	va_list ap;
+
+	free(last_error.msg);
+
+	last_error.code = errcode;
+	last_error.msg = NULL;
+
+	if (fmt) {
+		va_start(ap, fmt);
+		xvasprintf(&last_error.msg, fmt, ap);
+		va_end(ap);
+	}
+}
+
+static void init_env(void)
+{
+	static bool init_done = false;
+	struct rlimit limit = {
+		.rlim_cur = RLIM_INFINITY,
+		.rlim_max = RLIM_INFINITY,
+	};
+
+	if (init_done)
+		return;
+
+	setrlimit(RLIMIT_MEMLOCK, &limit);
+	init_done = true;
+}
+
+static uc_value_t *
+uc_bpf_error(uc_vm_t *vm, size_t nargs)
+{
+	uc_value_t *numeric = uc_fn_arg(0);
+	const char *msg = last_error.msg;
+	int code = last_error.code;
+	uc_stringbuf_t *buf;
+	const char *s;
+
+	if (last_error.code == 0)
+		return NULL;
+
+	set_error(0, NULL);
+
+	if (ucv_is_truish(numeric))
+		return ucv_int64_new(code);
+
+	buf = ucv_stringbuf_new();
+	if (code < 0 && msg) {
+		ucv_stringbuf_addstr(buf, msg, strlen(msg));
+	} else {
+		s = strerror(code);
+		ucv_stringbuf_addstr(buf, s, strlen(s));
+		if (msg)
+			ucv_stringbuf_printf(buf, ": %s", msg);
+	}
+
+	return ucv_stringbuf_finish(buf);
+}
+
+static int
+uc_bpf_module_set_opts(struct bpf_object *obj, uc_value_t *opts)
+{
+	uc_value_t *val;
+
+	if (!opts)
+		return 0;
+
+	if (ucv_type(opts) != UC_OBJECT)
+		err_return_int(EINVAL, "options argument");
+
+	if ((val = ucv_object_get(opts, "rodata", NULL)) != NULL) {
+		struct bpf_map *map = NULL;
+
+		if (ucv_type(val) != UC_STRING)
+			err_return_int(EINVAL, "rodata type");
+
+		while ((map = bpf_object__next_map(obj, map)) != NULL) {
+			if (!strstr(bpf_map__name(map), ".rodata"))
+				continue;
+
+			break;
+		}
+
+		if (!map)
+			err_return_int(errno, "rodata map");
+
+		if (bpf_map__set_initial_value(map, ucv_string_get(val),
+					       ucv_string_length(val)))
+			err_return_int(errno, "rodata");
+	}
+
+	if ((val = ucv_object_get(opts, "program-type", NULL)) != NULL) {
+		if (ucv_type(val) != UC_OBJECT)
+			err_return_int(EINVAL, "prog_types argument");
+
+		ucv_object_foreach(val, name, type) {
+			struct bpf_program *prog;
+
+			if (ucv_type(type) != UC_INTEGER)
+				err_return_int(EINVAL, "program %s type", name);
+
+			prog = bpf_object__find_program_by_name(obj, name);
+			if (!prog)
+				err_return_int(-1, "program %s not found", name);
+
+			bpf_program__set_type(prog, ucv_int64_get(type));
+		}
+	}
+
+	return 0;
+}
+
+static uc_value_t *
+uc_bpf_open_module(uc_vm_t *vm, size_t nargs)
+{
+	DECLARE_LIBBPF_OPTS(bpf_object_open_opts, bpf_opts);
+	uc_value_t *path = uc_fn_arg(0);
+	uc_value_t *opts = uc_fn_arg(1);
+	struct bpf_object *obj;
+
+	if (ucv_type(path) != UC_STRING)
+		err_return(EINVAL, "module path");
+
+	init_env();
+	obj = bpf_object__open_file(ucv_string_get(path), &bpf_opts);
+	if (libbpf_get_error(obj))
+		err_return(errno, NULL);
+
+	if (uc_bpf_module_set_opts(obj, opts)) {
+		bpf_object__close(obj);
+		return NULL;
+	}
+
+	if (bpf_object__load(obj)) {
+		bpf_object__close(obj);
+		err_return(errno, NULL);
+	}
+
+	return uc_resource_new(module_type, obj);
+}
+
+static uc_value_t *
+uc_bpf_map_create(int fd, unsigned int key_size, unsigned int val_size, bool close)
+{
+	struct uc_bpf_map *uc_map;
+
+	uc_map = xalloc(sizeof(*uc_map));
+	uc_map->fd.fd = fd;
+	uc_map->key_size = key_size;
+	uc_map->val_size = val_size;
+	uc_map->fd.close = close;
+
+	return uc_resource_new(map_type, uc_map);
+}
+
+static uc_value_t *
+uc_bpf_open_map(uc_vm_t *vm, size_t nargs)
+{
+	struct bpf_map_info info;
+	uc_value_t *path = uc_fn_arg(0);
+	__u32 len = sizeof(info);
+	int err;
+	int fd;
+
+	if (ucv_type(path) != UC_STRING)
+		err_return(EINVAL, "module path");
+
+	fd = bpf_obj_get(ucv_string_get(path));
+	if (fd < 0)
+		err_return(errno, NULL);
+
+	err = bpf_obj_get_info_by_fd(fd, &info, &len);
+	if (err) {
+		close(fd);
+		err_return(errno, NULL);
+	}
+
+	return uc_bpf_map_create(fd, info.key_size, info.value_size, true);
+}
+
+static uc_value_t *
+uc_bpf_open_program(uc_vm_t *vm, size_t nargs)
+{
+	uc_value_t *path = uc_fn_arg(0);
+	struct uc_bpf_fd *f;
+	int fd;
+
+	if (ucv_type(path) != UC_STRING)
+		err_return(EINVAL, "module path");
+
+	fd = bpf_obj_get(ucv_string_get(path));
+	if (fd < 0)
+		err_return(errno, NULL);
+
+	f = xalloc(sizeof(*f));
+	f->fd = fd;
+	f->close = true;
+
+	return uc_resource_new(program_type, f);
+}
+
+static uc_value_t *
+uc_bpf_module_get_maps(uc_vm_t *vm, size_t nargs)
+{
+	struct bpf_object *obj = uc_fn_thisval("bpf.module");
+	struct bpf_map *map = NULL;
+	uc_value_t *rv;
+	int i = 0;
+
+	if (!obj)
+		err_return(EINVAL, NULL);
+
+	rv = ucv_array_new(vm);
+	bpf_object__for_each_map(map, obj)
+		ucv_array_set(rv, i++, ucv_string_new(bpf_map__name(map)));
+
+	return rv;
+}
+
+static uc_value_t *
+uc_bpf_module_get_map(uc_vm_t *vm, size_t nargs)
+{
+	struct bpf_object *obj = uc_fn_thisval("bpf.module");
+	struct bpf_map *map;
+	uc_value_t *name = uc_fn_arg(0);
+	int fd;
+
+	if (!obj || ucv_type(name) != UC_STRING)
+		err_return(EINVAL, NULL);
+
+	map = bpf_object__find_map_by_name(obj, ucv_string_get(name));
+	if (!map)
+		err_return(errno, NULL);
+
+	fd = bpf_map__fd(map);
+	if (fd < 0)
+		err_return(EINVAL, NULL);
+
+	return uc_bpf_map_create(fd, bpf_map__key_size(map), bpf_map__value_size(map), false);
+}
+
+static uc_value_t *
+uc_bpf_module_get_programs(uc_vm_t *vm, size_t nargs)
+{
+	struct bpf_object *obj = uc_fn_thisval("bpf.module");
+	struct bpf_program *prog = NULL;
+	uc_value_t *rv;
+	int i = 0;
+
+	if (!obj)
+		err_return(EINVAL, NULL);
+
+	rv = ucv_array_new(vm);
+	bpf_object__for_each_program(prog, obj)
+		ucv_array_set(rv, i++, ucv_string_new(bpf_program__name(prog)));
+
+	return rv;
+}
+
+static uc_value_t *
+uc_bpf_module_get_program(uc_vm_t *vm, size_t nargs)
+{
+	struct bpf_object *obj = uc_fn_thisval("bpf.module");
+	struct bpf_program *prog;
+	uc_value_t *name = uc_fn_arg(0);
+	struct uc_bpf_fd *f;
+	int fd;
+
+	if (!obj || !name || ucv_type(name) != UC_STRING)
+		err_return(EINVAL, NULL);
+
+	prog = bpf_object__find_program_by_name(obj, ucv_string_get(name));
+	if (!prog)
+		err_return(errno, NULL);
+
+	fd = bpf_program__fd(prog);
+	if (fd < 0)
+		err_return(EINVAL, NULL);
+
+	f = xalloc(sizeof(*f));
+	f->fd = fd;
+
+	return uc_resource_new(program_type, f);
+}
+
+static void *
+uc_bpf_map_arg(uc_value_t *val, const char *kind, unsigned int size)
+{
+	static union {
+		uint32_t u32;
+		uint64_t u64;
+	} val_int;
+
+	switch (ucv_type(val)) {
+	case UC_INTEGER:
+		if (size == 4)
+			val_int.u32 = ucv_int64_get(val);
+		else if (size == 8)
+			val_int.u64 = ucv_int64_get(val);
+		else
+			break;
+
+		return &val_int;
+	case UC_STRING:
+		if (size != ucv_string_length(val))
+			break;
+
+		return ucv_string_get(val);
+	default:
+		err_return(EINVAL, "%s type", kind);
+	}
+
+	err_return(EINVAL, "%s size mismatch (expected: %d)", kind, size);
+}
+
+static uc_value_t *
+uc_bpf_map_get(uc_vm_t *vm, size_t nargs)
+{
+	struct uc_bpf_map *map = uc_fn_thisval("bpf.map");
+	uc_value_t *a_key = uc_fn_arg(0);
+	void *key, *val;
+
+	if (!map)
+		err_return(EINVAL, NULL);
+
+	key = uc_bpf_map_arg(a_key, "key", map->key_size);
+	if (!key)
+		return NULL;
+
+	val = alloca(map->val_size);
+	if (bpf_map_lookup_elem(map->fd.fd, key, val))
+		return NULL;
+
+	return ucv_string_new_length(val, map->val_size);
+}
+
+static uc_value_t *
+uc_bpf_map_set(uc_vm_t *vm, size_t nargs)
+{
+	struct uc_bpf_map *map = uc_fn_thisval("bpf.map");
+	uc_value_t *a_key = uc_fn_arg(0);
+	uc_value_t *a_val = uc_fn_arg(1);
+	uc_value_t *a_flags = uc_fn_arg(2);
+	uint64_t flags;
+	void *key, *val;
+
+	if (!map)
+		err_return(EINVAL, NULL);
+
+	key = uc_bpf_map_arg(a_key, "key", map->key_size);
+	if (!key)
+		return NULL;
+
+	val = uc_bpf_map_arg(a_val, "value", map->val_size);
+	if (!val)
+		return NULL;
+
+	if (!a_flags)
+		flags = BPF_ANY;
+	else if (ucv_type(a_flags) != UC_INTEGER)
+		err_return(EINVAL, "flags");
+	else
+		flags = ucv_int64_get(a_flags);
+
+	if (bpf_map_update_elem(map->fd.fd, key, val, flags))
+		return NULL;
+
+	return ucv_string_new_length(val, map->val_size);
+}
+
+static uc_value_t *
+uc_bpf_map_delete(uc_vm_t *vm, size_t nargs)
+{
+	struct uc_bpf_map *map = uc_fn_thisval("bpf.map");
+	uc_value_t *a_key = uc_fn_arg(0);
+	uc_value_t *a_return = uc_fn_arg(1);
+	void *key, *val = NULL;
+	int ret;
+
+	if (!map)
+		err_return(EINVAL, NULL);
+
+	key = uc_bpf_map_arg(a_key, "key", map->key_size);
+	if (!key)
+		return NULL;
+
+	if (!ucv_is_truish(a_return)) {
+		ret = bpf_map_delete_elem(map->fd.fd, key);
+
+		return ucv_boolean_new(ret == 0);
+	}
+
+	val = alloca(map->val_size);
+	if (bpf_map_lookup_and_delete_elem(map->fd.fd, key, val))
+		return NULL;
+
+	return ucv_string_new_length(val, map->val_size);
+}
+
+static uc_value_t *
+uc_bpf_map_delete_all(uc_vm_t *vm, size_t nargs)
+{
+	struct uc_bpf_map *map = uc_fn_thisval("bpf.map");
+	uc_value_t *filter = uc_fn_arg(0);
+	bool has_next;
+	void *key, *next;
+
+	if (!map)
+		err_return(EINVAL, NULL);
+
+	key = alloca(map->key_size);
+	next = alloca(map->key_size);
+	has_next = !bpf_map_get_next_key(map->fd.fd, NULL, next);
+	while (has_next) {
+		bool skip = false;
+
+		memcpy(key, next, map->key_size);
+		has_next = !bpf_map_get_next_key(map->fd.fd, next, next);
+
+		if (ucv_is_callable(filter)) {
+			uc_value_t *rv;
+
+			uc_value_push(ucv_get(filter));
+			uc_value_push(ucv_string_new_length((const char *)key, map->key_size));
+			if (uc_call(1) != EXCEPTION_NONE)
+				break;
+
+			rv = uc_vm_stack_pop(vm);
+			if (!rv)
+				break;
+
+			skip = !ucv_is_truish(rv);
+			ucv_put(rv);
+		}
+
+		if (!skip)
+			bpf_map_delete_elem(map->fd.fd, key);
+	}
+
+	return TRUE;
+}
+
+static uc_value_t *
+uc_bpf_map_iterator(uc_vm_t *vm, size_t nargs)
+{
+	struct uc_bpf_map *map = uc_fn_thisval("bpf.map");
+	struct uc_bpf_map_iter *iter;
+
+	if (!map)
+		err_return(EINVAL, NULL);
+
+	iter = xalloc(sizeof(*iter) + map->key_size);
+	iter->fd = map->fd.fd;
+	iter->key_size = map->key_size;
+	iter->has_next = !bpf_map_get_next_key(iter->fd, NULL, &iter->key);
+
+	return uc_resource_new(map_iter_type, iter);
+}
+
+static uc_value_t *
+uc_bpf_map_iter_next(uc_vm_t *vm, size_t nargs)
+{
+	struct uc_bpf_map_iter *iter = uc_fn_thisval("bpf.map_iter");
+	uc_value_t *rv;
+
+	if (!iter->has_next)
+		return NULL;
+
+	rv = ucv_string_new_length((const char *)iter->key, iter->key_size);
+	iter->has_next = !bpf_map_get_next_key(iter->fd, &iter->key, &iter->key);
+
+	return rv;
+}
+
+static uc_value_t *
+uc_bpf_map_iter_next_int(uc_vm_t *vm, size_t nargs)
+{
+	struct uc_bpf_map_iter *iter = uc_fn_thisval("bpf.map_iter");
+	uint64_t intval;
+	uc_value_t *rv;
+
+	if (!iter->has_next)
+		return NULL;
+
+	if (iter->key_size == 4)
+		intval = *(uint32_t *)iter->key;
+	else if (iter->key_size == 8)
+		intval = *(uint64_t *)iter->key;
+	else
+		return NULL;
+
+	rv = ucv_int64_new(intval);
+	iter->has_next = !bpf_map_get_next_key(iter->fd, &iter->key, &iter->key);
+
+	return rv;
+}
+
+static uc_value_t *
+uc_bpf_map_foreach(uc_vm_t *vm, size_t nargs)
+{
+	struct uc_bpf_map *map = uc_fn_thisval("bpf.map");
+	uc_value_t *func = uc_fn_arg(0);
+	bool has_next;
+	void *key, *next;
+	bool ret = false;
+
+	key = alloca(map->key_size);
+	next = alloca(map->key_size);
+	has_next = !bpf_map_get_next_key(map->fd.fd, NULL, next);
+
+	while (has_next) {
+		uc_value_t *rv;
+		bool stop;
+
+		memcpy(key, next, map->key_size);
+		has_next = !bpf_map_get_next_key(map->fd.fd, next, next);
+
+		uc_value_push(ucv_get(func));
+		uc_value_push(ucv_string_new_length((const char *)key, map->key_size));
+
+		if (uc_call(1) != EXCEPTION_NONE)
+			break;
+
+		rv = uc_vm_stack_pop(vm);
+		stop = (ucv_type(rv) == UC_BOOLEAN && !ucv_boolean_get(rv));
+		ucv_put(rv);
+
+		if (stop)
+			break;
+
+		ret = true;
+	}
+
+	return ucv_boolean_new(ret);
+}
+
+static uc_value_t *
+uc_bpf_obj_pin(uc_vm_t *vm, size_t nargs, const char *type)
+{
+	struct uc_bpf_fd *f = uc_fn_thisval(type);
+	uc_value_t *path = uc_fn_arg(0);
+
+	if (ucv_type(path) != UC_STRING)
+		err_return(EINVAL, NULL);
+
+	if (bpf_obj_pin(f->fd, ucv_string_get(path)))
+		err_return(errno, NULL);
+
+	return TRUE;
+}
+
+static uc_value_t *
+uc_bpf_program_pin(uc_vm_t *vm, size_t nargs)
+{
+	return uc_bpf_obj_pin(vm, nargs, "bpf.program");
+}
+
+static uc_value_t *
+uc_bpf_map_pin(uc_vm_t *vm, size_t nargs)
+{
+	return uc_bpf_obj_pin(vm, nargs, "bpf.map");
+}
+
+static uc_value_t *
+uc_bpf_set_tc_hook(uc_value_t *ifname, uc_value_t *type, uc_value_t *prio,
+		   int fd)
+{
+	DECLARE_LIBBPF_OPTS(bpf_tc_hook, hook);
+	DECLARE_LIBBPF_OPTS(bpf_tc_opts, attach_tc,
+			    .handle = 1);
+	const char *type_str;
+	uint64_t prio_val;
+
+	if (ucv_type(ifname) != UC_STRING || ucv_type(type) != UC_STRING ||
+	    ucv_type(prio) != UC_INTEGER)
+		err_return(EINVAL, NULL);
+
+	prio_val = ucv_int64_get(prio);
+	if (prio_val > 0xffff)
+		err_return(EINVAL, NULL);
+
+	type_str = ucv_string_get(type);
+	if (!strcmp(type_str, "ingress"))
+		hook.attach_point = BPF_TC_INGRESS;
+	else if (!strcmp(type_str, "egress"))
+		hook.attach_point = BPF_TC_EGRESS;
+	else
+		err_return(EINVAL, NULL);
+
+	hook.ifindex = if_nametoindex(ucv_string_get(ifname));
+	if (!hook.ifindex)
+		goto error;
+
+	bpf_tc_hook_create(&hook);
+	attach_tc.priority = prio_val;
+	if (bpf_tc_detach(&hook, &attach_tc) < 0 && fd < 0)
+		goto error;
+
+	if (fd < 0)
+		goto out;
+
+	attach_tc.prog_fd = fd;
+	if (bpf_tc_attach(&hook, &attach_tc) < 0)
+		goto error;
+
+out:
+	return TRUE;
+
+error:
+	if (fd >= 0)
+		err_return(ENOENT, NULL);
+	return NULL;
+}
+
+static uc_value_t *
+uc_bpf_program_tc_attach(uc_vm_t *vm, size_t nargs)
+{
+	struct uc_bpf_fd *f = uc_fn_thisval("bpf.program");
+	uc_value_t *ifname = uc_fn_arg(0);
+	uc_value_t *type = uc_fn_arg(1);
+	uc_value_t *prio = uc_fn_arg(2);
+
+	if (!f)
+		err_return(EINVAL, NULL);
+
+	return uc_bpf_set_tc_hook(ifname, type, prio, f->fd);
+}
+
+static uc_value_t *
+uc_bpf_tc_detach(uc_vm_t *vm, size_t nargs)
+{
+	uc_value_t *ifname = uc_fn_arg(0);
+	uc_value_t *type = uc_fn_arg(1);
+	uc_value_t *prio = uc_fn_arg(2);
+
+	return uc_bpf_set_tc_hook(ifname, type, prio, -1);
+}
+
+static int
+uc_bpf_debug_print(enum libbpf_print_level level, const char *format,
+		   va_list args)
+{
+	char buf[256], *str = NULL;
+	uc_value_t *val;
+	va_list ap;
+	int size;
+
+	va_copy(ap, args);
+	size = vsnprintf(buf, sizeof(buf), format, ap);
+	va_end(ap);
+
+	if (size > 0 && (unsigned long)size < ARRAY_SIZE(buf) - 1) {
+		val = ucv_string_new(buf);
+		goto out;
+	}
+
+	if (vasprintf(&str, format, args) < 0)
+		return 0;
+
+	val = ucv_string_new(str);
+	free(str);
+
+out:
+	uc_vm_stack_push(debug_vm, ucv_get(ucv_array_get(registry, 0)));
+	uc_vm_stack_push(debug_vm, ucv_int64_new(level));
+	uc_vm_stack_push(debug_vm, val);
+	if (uc_vm_call(debug_vm, false, 2) == EXCEPTION_NONE)
+		ucv_put(uc_vm_stack_pop(debug_vm));
+
+	return 0;
+}
+
+static uc_value_t *
+uc_bpf_set_debug_handler(uc_vm_t *vm, size_t nargs)
+{
+	uc_value_t *handler = uc_fn_arg(0);
+
+	if (handler && !ucv_is_callable(handler))
+		err_return(EINVAL, NULL);
+
+	debug_vm = vm;
+	libbpf_set_print(handler ? uc_bpf_debug_print : NULL);
+
+	ucv_array_set(registry, 0, ucv_get(handler));
+
+	return NULL;
+}
+
+static void
+register_constants(uc_vm_t *vm, uc_value_t *scope)
+{
+#define ADD_CONST(x) ucv_object_add(scope, #x, ucv_int64_new(x))
+	ADD_CONST(BPF_PROG_TYPE_SCHED_CLS);
+	ADD_CONST(BPF_PROG_TYPE_SCHED_ACT);
+
+	ADD_CONST(BPF_ANY);
+	ADD_CONST(BPF_NOEXIST);
+	ADD_CONST(BPF_EXIST);
+	ADD_CONST(BPF_F_LOCK);
+}
+
+static const uc_function_list_t module_fns[] = {
+	{ "get_map",			uc_bpf_module_get_map },
+	{ "get_maps",			uc_bpf_module_get_maps },
+	{ "get_programs",		uc_bpf_module_get_programs },
+	{ "get_program",		uc_bpf_module_get_program },
+};
+
+static void module_free(void *ptr)
+{
+	struct bpf_object *obj = ptr;
+
+	bpf_object__close(obj);
+}
+
+static const uc_function_list_t map_fns[] = {
+	{ "pin",			uc_bpf_map_pin },
+	{ "get",			uc_bpf_map_get },
+	{ "set",			uc_bpf_map_set },
+	{ "delete",			uc_bpf_map_delete },
+	{ "delete_all",			uc_bpf_map_delete_all },
+	{ "foreach",			uc_bpf_map_foreach },
+	{ "iterator",			uc_bpf_map_iterator },
+};
+
+static void uc_bpf_fd_free(void *ptr)
+{
+	struct uc_bpf_fd *f = ptr;
+
+	if (f->close)
+		close(f->fd);
+	free(f);
+}
+
+static const uc_function_list_t map_iter_fns[] = {
+	{ "next",			uc_bpf_map_iter_next },
+	{ "next_int",			uc_bpf_map_iter_next_int },
+};
+
+static const uc_function_list_t prog_fns[] = {
+	{ "pin",			uc_bpf_program_pin },
+	{ "tc_attach",			uc_bpf_program_tc_attach },
+};
+
+static const uc_function_list_t global_fns[] = {
+	{ "error",			uc_bpf_error },
+	{ "set_debug_handler",		uc_bpf_set_debug_handler },
+	{ "open_module",		uc_bpf_open_module },
+	{ "open_map",			uc_bpf_open_map },
+	{ "open_program",		uc_bpf_open_program },
+	{ "tc_detach",			uc_bpf_tc_detach },
+};
+
+void uc_module_init(uc_vm_t *vm, uc_value_t *scope)
+{
+	uc_function_list_register(scope, global_fns);
+	register_constants(vm, scope);
+
+	registry = ucv_array_new(vm);
+	uc_vm_registry_set(vm, "bpf.registry", registry);
+
+	module_type = uc_type_declare(vm, "bpf.module", module_fns, module_free);
+	map_type = uc_type_declare(vm, "bpf.map", map_fns, uc_bpf_fd_free);
+	map_iter_type = uc_type_declare(vm, "bpf.map_iter", map_iter_fns, free);
+	program_type = uc_type_declare(vm, "bpf.program", prog_fns, uc_bpf_fd_free);
+}
diff --git a/package/utils/ucode/Makefile b/package/utils/ucode/Makefile
new file mode 100644
index 0000000..9eb721f
--- /dev/null
+++ b/package/utils/ucode/Makefile
@@ -0,0 +1,193 @@
+#
+# Copyright (C) 2020-2021 Jo-Philipp Wich <jo@mein.io>
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=ucode
+PKG_RELEASE:=1
+
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_URL=https://github.com/jow-/ucode.git
+PKG_SOURCE_DATE:=2025-02-10
+PKG_SOURCE_VERSION:=a8a11aea0c093d669bb3c45f604dab3c291c8d25
+PKG_MIRROR_HASH:=4de0094bc641fc13ff13516ca80d8265bf6eed6d9a9b90fdf84b7a558d505acc
+PKG_MAINTAINER:=Jo-Philipp Wich <jo@mein.io>
+PKG_LICENSE:=ISC
+
+PKG_ABI_VERSION:=20230711
+PKG_BUILD_DEPENDS:=libmd
+HOST_BUILD_DEPENDS:=libjson-c/host
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/host-build.mk
+include $(INCLUDE_DIR)/cmake.mk
+
+CMAKE_OPTIONS += \
+	-DSOVERSION=$(PKG_ABI_VERSION)
+
+CMAKE_HOST_OPTIONS += \
+	-DCMAKE_SKIP_RPATH=FALSE \
+	-DCMAKE_INSTALL_RPATH="${STAGING_DIR_HOSTPKG}/lib"
+
+ifeq ($(HOST_OS),Darwin)
+  CMAKE_HOST_OPTIONS += \
+	-DCMAKE_MACOSX_RPATH=1
+else
+  CMAKE_HOST_OPTIONS += \
+	-DUSE_RPATH="${STAGING_DIR_HOSTPKG}/lib"
+endif
+
+CMAKE_HOST_OPTIONS += \
+	-DFS_SUPPORT=ON \
+	-DMATH_SUPPORT=ON \
+	-DNL80211_SUPPORT=OFF \
+	-DRESOLV_SUPPORT=OFF \
+	-DRTNL_SUPPORT=OFF \
+	-DSTRUCT_SUPPORT=ON \
+	-DUBUS_SUPPORT=OFF \
+	-DUCI_SUPPORT=OFF \
+	-DULOOP_SUPPORT=OFF \
+	-DDEBUG_SUPPORT=ON \
+	-DLOG_SUPPORT=OFF \
+	-DDIGEST_SUPPORT=OFF
+
+
+define Package/ucode/default
+  SUBMENU:=ucode
+  SECTION:=lang
+  CATEGORY:=Languages
+  TITLE:=Tiny scripting and templating language
+endef
+
+define Package/ucode
+  $(Package/ucode/default)
+  DEPENDS:=+libucode
+endef
+
+define Package/ucode/description
+ ucode is a tiny script interpreter featuring an ECMAScript oriented
+ script language and Jinja-inspired templating.
+endef
+
+
+define Package/libucode
+  $(Package/ucode/default)
+  SUBMENU:=
+  SECTION:=libs
+  CATEGORY:=Libraries
+  TITLE+= (library)
+  ABI_VERSION:=$(PKG_ABI_VERSION)
+  DEPENDS:=+libjson-c
+endef
+
+define Package/libucode/description
+ The libucode package provides the shared runtime library for the ucode interpreter.
+endef
+
+# 1: name
+# 2: cmake symbol
+# 3: depends
+# 4: description
+define UcodeModule
+  UCODE_MODULES += ucode-mod-$(strip $(1))
+  CMAKE_OPTIONS += -D$(strip $(2))=$(if $(CONFIG_PACKAGE_ucode-mod-$(strip $(1))),ON,OFF)
+  PKG_CONFIG_DEPENDS += CONFIG_PACKAGE_ucode-mod-$(strip $(1))
+
+ define Package/ucode-mod-$(strip $(1))
+  $(Package/ucode/default)
+  TITLE+= ($(strip $(1)) module)
+  DEPENDS:=+ucode $(3)
+ endef
+
+ define Package/ucode-mod-$(strip $(1))/description
+ $(strip $(4))
+ endef
+
+ define Package/ucode-mod-$(strip $(1))/install
+	$(INSTALL_DIR) $$(1)/usr/lib/ucode
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/ucode/$(strip $(1)).so $$(1)/usr/lib/ucode/
+ endef
+endef
+
+
+define Build/InstallDev
+	$(INSTALL_DIR) $(1)/usr/lib $(1)/usr/include/ucode
+	$(CP) $(PKG_INSTALL_DIR)/usr/include/ucode/*.h $(1)/usr/include/ucode/
+	$(CP) $(PKG_INSTALL_DIR)/usr/lib/libucode.so* $(1)/usr/lib/
+endef
+
+
+define Package/ucode/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(CP) $(PKG_INSTALL_DIR)/usr/bin/u* $(1)/usr/bin/
+endef
+
+define Package/libucode/install
+	$(INSTALL_DIR) $(1)/usr/lib
+	$(CP) $(PKG_INSTALL_DIR)/usr/lib/libucode.so.* $(1)/usr/lib/
+endef
+
+
+$(eval $(call UcodeModule, \
+	debug, DEBUG_SUPPORT, +libubox +libucode, \
+	The debug plugin module provides runtime debugging and introspection facilities.))
+
+$(eval $(call UcodeModule, \
+	fs, FS_SUPPORT, , \
+	The filesystem plugin module allows interaction with the local file system.))
+
+$(eval $(call UcodeModule, \
+	log, LOG_SUPPORT, +libubox, \
+	The log plugin module provides access to the syslog and libubox ulog APIs.))
+
+$(eval $(call UcodeModule, \
+	math, MATH_SUPPORT, , \
+	The math plugin provides access to various <math.h> procedures.))
+
+$(eval $(call UcodeModule, \
+	nl80211, NL80211_SUPPORT, +libnl-tiny +libubox, \
+	The nl80211 plugin provides access to the Linux wireless 802.11 netlink API.))
+
+$(eval $(call UcodeModule, \
+	resolv, RESOLV_SUPPORT, , \
+	The resolv plugin implements simple DNS resolving.))
+
+$(eval $(call UcodeModule, \
+	rtnl, RTNL_SUPPORT, +libnl-tiny +libubox, \
+	The rtnl plugin provides access to the Linux routing netlink API.))
+
+$(eval $(call UcodeModule, \
+	socket, SOCKET_SUPPORT, , \
+	The socket plugin provides access to IPv4, IPv6, Unix and packet socket APIs.))
+
+$(eval $(call UcodeModule, \
+	struct, STRUCT_SUPPORT, , \
+	The struct plugin implements Python 3 compatible struct.pack/unpack functionality.))
+
+$(eval $(call UcodeModule, \
+	ubus, UBUS_SUPPORT, +libubus +libblobmsg-json, \
+	The ubus module allows ucode template scripts to enumerate and invoke ubus procedures.))
+
+$(eval $(call UcodeModule, \
+	uci, UCI_SUPPORT, +libuci, \
+	The uci module allows templates to read and modify uci configuration.))
+
+$(eval $(call UcodeModule, \
+	uloop, ULOOP_SUPPORT, +libubox, \
+	The uloop module allows ucode scripts to interact with OpenWrt uloop event loop implementation.))
+
+$(eval $(call UcodeModule, \
+	digest, DIGEST_SUPPORT, , \
+	The digest module allows ucode scripts to use libmd digests.))
+
+$(eval $(call BuildPackage,libucode))
+$(eval $(call BuildPackage,ucode))
+
+$(foreach mod,$(UCODE_MODULES), \
+	$(eval $(call BuildPackage,$(mod))))
+
+$(eval $(call HostBuild))
diff --git a/package/utils/uencrypt/Makefile b/package/utils/uencrypt/Makefile
new file mode 100644
index 0000000..70ca655
--- /dev/null
+++ b/package/utils/uencrypt/Makefile
@@ -0,0 +1,85 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Copyright (C) 2022 Eneas Ulir de Queiroz
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=uencrypt
+PKG_RELEASE:=5
+
+PKG_LICENSE:=GPL-2.0-or-later
+PKG_MAINTAINER:=Eneas U de Queiroz <cotequeiroz@gmail.com>
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/cmake.mk
+
+CMAKE_INSTALL:=1
+ifeq ($(BUILD_VARIANT),mbedtls)
+  CMAKE_OPTIONS+=-DUSE_MBEDTLS=1
+else ifeq ($(BUILD_VARIANT),wolfssl)
+  CMAKE_OPTIONS+=-DUSE_WOLFSSL=1
+endif
+
+TARGET_CFLAGS+=-Wall
+
+define Package/uencrypt/default
+  SECTION:=utils
+  CATEGORY:=Base system
+  TITLE:=Small Decryption utility
+endef
+
+define Package/uencrypt/default/description
+  This is a small encrypton/decryption program. It defaults
+  to AES-128-CBC, but supports any encryption provided by
+  the crypto library. Even though it can be used for
+  non-critical* regular encryption and decryption operations,
+  it is included here to unencrypt the configuration from mtd
+  on some devices.
+
+  * Key and IV are exposed on cmdline
+
+  This variant uses $(1) as crypto provider
+endef
+
+define Package/uencrypt-mbedtls
+  $(Package/uencrypt/default)
+  VARIANT:=mbedtls
+  TITLE+= using mbedTLS
+  DEPENDS:=+libmbedtls
+  CONFLICTS:=uencrypt-openssl uencrypt-wolfssl
+endef
+
+Package/uencrypt-mbedtls/description= \
+  $(call Package/uencrypt/default/description,mbedTLS)
+
+define Package/uencrypt-openssl
+  $(Package/uencrypt/default)
+  VARIANT:=openssl
+  TITLE+= using OpenSSL
+  DEPENDS:=+libopenssl
+  CONFLICTS:=uencrypt-wolfssl
+endef
+
+Package/uencrypt-openssl/description= \
+  $(call Package/uencrypt/default/description,OpenSSL)
+
+define Package/uencrypt-wolfssl
+  $(Package/uencrypt/default)
+  VARIANT:=wolfssl
+  TITLE+= using wolfSSL
+  DEPENDS:=+libwolfssl
+endef
+
+Package/uencrypt-wolfssl/description= \
+  $(call Package/uencrypt/default/description,wolfSSL)
+
+define Package/uencrypt/default/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/uencrypt $(1)/usr/bin
+endef
+Package/uencrypt-openssl/install = $(Package/uencrypt/default/install)
+Package/uencrypt-wolfssl/install = $(Package/uencrypt/default/install)
+Package/uencrypt-mbedtls/install = $(Package/uencrypt/default/install)
+
+$(eval $(call BuildPackage,uencrypt-mbedtls))
+$(eval $(call BuildPackage,uencrypt-openssl))
+$(eval $(call BuildPackage,uencrypt-wolfssl))
diff --git a/package/utils/uencrypt/src/CMakeLists.txt b/package/utils/uencrypt/src/CMakeLists.txt
new file mode 100644
index 0000000..5e09954
--- /dev/null
+++ b/package/utils/uencrypt/src/CMakeLists.txt
@@ -0,0 +1,32 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Copyright (C) 2022 Eneas Ulir de Queiroz
+
+cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR)
+project(uencrypt LANGUAGES C)
+
+option(USE_WOLFSSL "Use WolfSSL as crypto provider" OFF)
+option(USE_MBEDTLS "Use mbedTLS as crypto provider" OFF)
+if (USE_MBEDTLS)
+	if (USE_WOLFSSL)
+		message(WARNING "USE_MBEDTLS and USE_WOLFSSL are both set. Building with USE_MBEDTLS.")
+	endif()
+	add_definitions(-DUSE_MBEDTLS)
+	find_library(MBEDCRYPTO_LIBRARY mbedcrypto REQUIRED)
+	set(CRYPTO_LIBRARIES ${MBEDCRYPTO_LIBRARY})
+	set(CRYPTO_SOURCES ${PROJECT_NAME}-mbedtls.c)
+else()
+	set(CRYPTO_SOURCES ${PROJECT_NAME}-openssl.c)
+	if (USE_WOLFSSL)
+		add_definitions(-DUSE_WOLFSSL)
+		find_library(WOLFSSL_LIBRARY wolfssl REQUIRED)
+		set(CRYPTO_LIBRARIES ${WOLFSSL_LIBRARY})
+	else()
+		find_package(OpenSSL REQUIRED)
+		set(CRYPTO_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY})
+	endif()
+endif()
+add_executable(${PROJECT_NAME} ${PROJECT_NAME}.c ${PROJECT_NAME}.h ${CRYPTO_SOURCES})
+
+target_link_libraries(${PROJECT_NAME} ${CRYPTO_LIBRARIES})
+
+install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION bin)
diff --git a/package/utils/uencrypt/src/uencrypt-mbedtls.c b/package/utils/uencrypt/src/uencrypt-mbedtls.c
new file mode 100644
index 0000000..119d07b
--- /dev/null
+++ b/package/utils/uencrypt/src/uencrypt-mbedtls.c
@@ -0,0 +1,238 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright (C) 2023 Eneas Ulir de Queiroz
+ */
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "uencrypt.h"
+
+#if MBEDTLS_VERSION_NUMBER < 0x03010000 /* mbedtls 3.1.0 */
+static inline mbedtls_cipher_mode_t mbedtls_cipher_info_get_mode(
+    const mbedtls_cipher_info_t *info)
+{
+    if (info == NULL) {
+        return MBEDTLS_MODE_NONE;
+    } else {
+        return info->mode;
+    }
+}
+
+static inline size_t mbedtls_cipher_info_get_key_bitlen(
+    const mbedtls_cipher_info_t *info)
+{
+    if (info == NULL) {
+        return 0;
+    } else {
+        return info->key_bitlen;
+    }
+}
+
+static inline const char *mbedtls_cipher_info_get_name(
+    const mbedtls_cipher_info_t *info)
+{
+    if (info == NULL) {
+        return NULL;
+    } else {
+        return info->name;
+    }
+}
+
+static inline size_t mbedtls_cipher_info_get_iv_size(
+    const mbedtls_cipher_info_t *info)
+{
+    if (info == NULL) {
+        return 0;
+    }
+
+    return info->iv_size;
+}
+
+static inline size_t mbedtls_cipher_info_get_block_size(
+    const mbedtls_cipher_info_t *info)
+{
+    if (info == NULL) {
+        return 0;
+    }
+
+    return info->block_size;
+}
+#endif
+
+unsigned char *hexstr2buf(const char *str, long *len)
+{
+    unsigned char *buf;
+    long inlen = strlen(str);
+
+    *len = 0;
+    if (inlen % 2)
+	return NULL;
+
+    *len = inlen >> 1;
+    buf = malloc(*len);
+    for  (long x = 0; x < *len; x++)
+	sscanf(str + x * 2, "%2hhx", buf + x);
+    return buf;
+}
+
+const cipher_t *get_default_cipher(void)
+{
+    return mbedtls_cipher_info_from_type (MBEDTLS_CIPHER_AES_128_CBC);
+}
+
+static char* upperstr(char *str) {
+    for (char *s = str; *s; s++)
+	*s = toupper((unsigned char) *s);
+    return str;
+}
+
+const cipher_t *get_cipher_or_print_error(char *name)
+{
+    const mbedtls_cipher_info_t *cipher;
+
+    cipher = mbedtls_cipher_info_from_string(upperstr(name));
+    if (cipher)
+	return cipher;
+
+    fprintf(stderr, "Error: invalid cipher: %s.\n", name);
+    fprintf(stderr, "Supported ciphers: \n");
+    for (const int *list = mbedtls_cipher_list(); *list; list++) {
+	cipher = mbedtls_cipher_info_from_type(*list);
+	if (!cipher)
+	    continue;
+	fprintf(stderr, "\t%s\n", mbedtls_cipher_info_get_name(cipher));
+    }
+    return NULL;
+}
+
+int get_cipher_ivsize(const cipher_t *cipher)
+{
+    const mbedtls_cipher_info_t *c = cipher;
+
+    return mbedtls_cipher_info_get_iv_size(c);
+}
+
+int get_cipher_keysize(const cipher_t *cipher)
+{
+    const mbedtls_cipher_info_t *c = cipher;
+
+    return mbedtls_cipher_info_get_key_bitlen(c) >> 3;
+}
+
+ctx_t *create_ctx(const cipher_t *cipher, const unsigned char *key,
+		  const unsigned char *iv, int enc, int padding)
+{
+    mbedtls_cipher_context_t *ctx;
+    const mbedtls_cipher_info_t *cipher_info=cipher;
+    int ret;
+
+    ctx = malloc(sizeof (mbedtls_cipher_context_t));
+    if (!ctx) {
+	fprintf (stderr, "Error: create_ctx: out of memory.\n");
+	return NULL;
+    }
+
+    mbedtls_cipher_init(ctx);
+    ret = mbedtls_cipher_setup(ctx, cipher_info);
+    if (ret) {
+	fprintf(stderr, "Error: mbedtls_cipher_setup: %d\n", ret);
+	goto abort;
+    }
+    ret = mbedtls_cipher_setkey(ctx, key,
+				(int) mbedtls_cipher_get_key_bitlen(ctx),
+				enc ? MBEDTLS_ENCRYPT : MBEDTLS_DECRYPT);
+    if (ret) {
+	fprintf(stderr, "Error: mbedtls_cipher_setkey: %d\n", ret);
+	goto abort;
+    }
+    if (iv) {
+        ret = mbedtls_cipher_set_iv(ctx, iv, mbedtls_cipher_get_iv_size(ctx));
+	if (ret) {
+	    fprintf(stderr, "Error: mbedtls_cipher_set_iv: %d\n", ret);
+	    goto abort;
+	}
+    }
+
+    if (mbedtls_cipher_info_get_mode(cipher_info) == MBEDTLS_MODE_CBC) {
+	ret = mbedtls_cipher_set_padding_mode(ctx, padding ?
+						   MBEDTLS_PADDING_PKCS7 :
+						   MBEDTLS_PADDING_NONE);
+	if (ret) {
+	    fprintf(stderr, "Error: mbedtls_cipher_set_padding_mode: %d\n",
+		    ret);
+	    goto abort;
+	}
+    } else {
+	if (mbedtls_cipher_info_get_block_size(cipher_info) > 1 && padding) {
+	    fprintf(stderr,
+		    "Error: mbedTLS only allows padding with CBC ciphers.\n");
+	    goto abort;
+	}
+    }
+
+    ret = mbedtls_cipher_reset(ctx);
+    if (ret) {
+	fprintf(stderr, "Error: mbedtls_cipher_reset: %d\n", ret);
+	goto abort;
+    }
+    return ctx;
+
+abort:
+    free_ctx(ctx);
+    return NULL;
+}
+
+int do_crypt(FILE *infile, FILE *outfile, ctx_t *ctx)
+{
+    unsigned char inbuf[CRYPT_BUF_SIZE];
+    unsigned char outbuf[CRYPT_BUF_SIZE + MBEDTLS_MAX_BLOCK_LENGTH];
+    size_t inlen, outlen, step;
+    int ret;
+
+    if (mbedtls_cipher_get_cipher_mode(ctx) == MBEDTLS_MODE_ECB) {
+	step = mbedtls_cipher_get_block_size(ctx);
+	if (step > CRYPT_BUF_SIZE) {
+	    step = CRYPT_BUF_SIZE;
+	}
+    } else {
+	step = CRYPT_BUF_SIZE;
+    }
+
+    for (;;) {
+	inlen = fread(inbuf, 1, step, infile);
+	if (inlen <= 0)
+	    break;
+	ret = mbedtls_cipher_update(ctx, inbuf, inlen, outbuf, &outlen);
+	if (ret) {
+	    fprintf(stderr, "Error: mbedtls_cipher_update: %d\n", ret);
+	    return ret;
+	}
+	ret = fwrite(outbuf, 1, outlen, outfile);
+	if (ret != outlen) {
+	    fprintf(stderr, "Error: cipher_update short write.\n");
+	    return ret - outlen;
+	}
+    }
+    ret = mbedtls_cipher_finish(ctx, outbuf, &outlen);
+    if (ret) {
+	fprintf(stderr, "Error: mbedtls_cipher_finish: %d\n", ret);
+	return ret;
+    }
+    ret = fwrite(outbuf, 1, outlen, outfile);
+    if (ret != outlen) {
+	fprintf(stderr, "Error: cipher_finish short write.\n");
+	return ret - outlen;
+    }
+
+    return 0;
+}
+
+void free_ctx(ctx_t *ctx)
+{
+    if (ctx) {
+	mbedtls_cipher_free(ctx);
+	free(ctx);
+    }
+}
diff --git a/package/utils/uencrypt/src/uencrypt-openssl.c b/package/utils/uencrypt/src/uencrypt-openssl.c
new file mode 100644
index 0000000..d9182be
--- /dev/null
+++ b/package/utils/uencrypt/src/uencrypt-openssl.c
@@ -0,0 +1,116 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright (C) 2022-2023 Eneas Ulir de Queiroz
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "uencrypt.h"
+
+const cipher_t *get_default_cipher(void)
+{
+    return EVP_aes_128_cbc();
+}
+
+#ifndef USE_WOLFSSL
+static void print_ciphers(const OBJ_NAME *name,void *arg) {
+    fprintf(arg, "\t%s\n", name->name);
+}
+#endif
+
+const cipher_t *get_cipher_or_print_error(char *name)
+{
+    const EVP_CIPHER *cipher;
+
+    if ((cipher = EVP_get_cipherbyname(name)))
+	return cipher;
+
+    fprintf(stderr, "Error: invalid cipher: %s.\n", name);
+#ifndef USE_WOLFSSL
+    fprintf(stderr, "Supported ciphers: \n");
+    OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_CIPHER_METH, print_ciphers, stderr);
+#endif
+    return NULL;
+}
+
+int get_cipher_ivsize(const cipher_t *cipher)
+{
+    return EVP_CIPHER_iv_length(cipher);
+}
+
+int get_cipher_keysize(const cipher_t *cipher)
+{
+    return EVP_CIPHER_key_length(cipher);
+}
+
+ctx_t *create_ctx(const cipher_t *cipher, const unsigned char *key,
+		  const unsigned char *iv, int enc, int padding)
+{
+    EVP_CIPHER_CTX *ctx;
+    int ret;
+
+    ctx = EVP_CIPHER_CTX_new();
+    if (!ctx) {
+	fprintf (stderr, "Error: create_ctx: out of memory.\n");
+	return NULL;
+    }
+    ret = EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, enc);
+    if (!ret) {
+	fprintf(stderr, "Error:EVP_CipherInit_ex: %d\n", ret);
+	goto abort;
+    }
+    ret = EVP_CIPHER_CTX_set_padding(ctx, padding);
+    if (!ret) {
+	fprintf(stderr, "Error:EVP_CIPHER_CTX_set_padding: %d\n", ret);
+	goto abort;
+    }
+
+    return ctx;
+
+abort:
+    free_ctx(ctx);
+    return NULL;
+}
+
+
+int do_crypt(FILE *infile, FILE *outfile, ctx_t *ctx)
+{
+    unsigned char inbuf[CRYPT_BUF_SIZE];
+    unsigned char outbuf[CRYPT_BUF_SIZE + EVP_MAX_BLOCK_LENGTH];
+    int inlen, outlen;
+    int ret;
+
+    for (;;) {
+	inlen = fread(inbuf, 1, CRYPT_BUF_SIZE, infile);
+	if (inlen <= 0)
+	    break;
+	ret = EVP_CipherUpdate(ctx, outbuf, &outlen, inbuf, inlen);
+	if (!ret) {
+	    fprintf(stderr, "Error: EVP_CipherUpdate: %d\n", ret);
+	    return ret;
+	}
+	ret = fwrite(outbuf, 1, outlen, outfile);
+	if (ret != outlen) {
+	    fprintf(stderr, "Error: CipherUpdate short write.\n");
+	    return ret - outlen;
+	}
+    }
+    ret = EVP_CipherFinal_ex(ctx, outbuf, &outlen);
+    if (!ret) {
+	fprintf(stderr, "Error: EVP_CipherFinal: %d\n", ret);
+	return ret;
+    }
+    ret = fwrite(outbuf, 1, outlen, outfile);
+    if (ret != outlen) {
+	fprintf(stderr, "Error: CipherFinal short write.\n");
+	return ret - outlen;
+    }
+
+    return 0;
+}
+
+void free_ctx(ctx_t *ctx)
+{
+    EVP_CIPHER_CTX_free(ctx);
+}
diff --git a/package/utils/uencrypt/src/uencrypt.c b/package/utils/uencrypt/src/uencrypt.c
new file mode 100644
index 0000000..a49db6e
--- /dev/null
+++ b/package/utils/uencrypt/src/uencrypt.c
@@ -0,0 +1,105 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright (C) 2023 Eneas Ulir de Queiroz
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "uencrypt.h"
+
+static void check_enc_dec(const int enc)
+{
+    if (enc == -1)
+	return;
+    fprintf(stderr, "Error: both -d and -e were specified.\n");
+    exit(EXIT_FAILURE);
+}
+
+static void show_usage(const char* name)
+{
+    fprintf(stderr, "Usage: %s: [-d | -e] [-n] -k key [-i iv] [-c cipher]\n"
+		    "-d = decrypt; -e = encrypt; -n = no padding\n", name);
+}
+
+static void uencrypt_clear_free(void *ptr, size_t len)
+{
+    if (ptr) {
+	memset(ptr, 0, len);
+	free(ptr);
+    }
+}
+
+int main(int argc, char *argv[])
+{
+    int enc = -1;
+    unsigned char *iv = NULL;
+    unsigned char *key = NULL;
+    long keylen = 0, ivlen = 0;
+    int opt;
+    int padding = 1;
+    const cipher_t *cipher = get_default_cipher();
+    ctx_t* ctx;
+    int ret = EXIT_FAILURE;
+
+    while ((opt = getopt(argc, argv, "c:dei:k:n")) != -1) {
+	switch (opt) {
+	case 'c':
+	    if (!(cipher = get_cipher_or_print_error(optarg)))
+		exit(EXIT_FAILURE);
+	    break;
+	case 'd':
+	    check_enc_dec(enc);
+	    enc = 0;
+	    break;
+	case 'e':
+	    check_enc_dec(enc);
+	    enc = 1;
+	    break;
+	case 'i':
+	    iv = hexstr2buf(optarg, &ivlen);
+	    if (iv == NULL) {
+		fprintf(stderr, "Error setting IV to %s. The IV should be encoded in hex.\n",
+			optarg);
+		exit(EINVAL);
+	    }
+	    memset(optarg, '*', strlen(optarg));
+	    break;
+	case 'k':
+	    key = hexstr2buf(optarg, &keylen);
+	    if (key == NULL) {
+		fprintf(stderr, "Error setting key to %s. The key should be encoded in hex.\n",
+			optarg);
+		exit(EINVAL);
+	    }
+	    memset(optarg, '*', strlen(optarg));
+	    break;
+	case 'n':
+	    padding = 0;
+	    break;
+	default:
+	    show_usage(argv[0]);
+	    exit(EINVAL);
+	}
+    }
+    if (ivlen != get_cipher_ivsize(cipher)) {
+	fprintf(stderr, "Error: IV must be %d bytes; given IV is %ld bytes.\n",
+		get_cipher_ivsize(cipher), ivlen);
+	exit(EXIT_FAILURE);
+    }
+    if (keylen != get_cipher_keysize(cipher)) {
+	fprintf(stderr, "Error: key must be %d bytes; given key is %ld bytes.\n",
+		get_cipher_keysize(cipher), keylen);
+	exit(EXIT_FAILURE);
+    }
+    ctx = create_ctx(cipher, key, iv, !!enc, padding);
+    if (ctx) {
+	ret = do_crypt(stdin, stdout, ctx);
+	free_ctx(ctx);
+    }
+    uencrypt_clear_free(iv, ivlen);
+    uencrypt_clear_free(key, keylen);
+    return ret;
+}
diff --git a/package/utils/uencrypt/src/uencrypt.h b/package/utils/uencrypt/src/uencrypt.h
new file mode 100644
index 0000000..a4fe1f3
--- /dev/null
+++ b/package/utils/uencrypt/src/uencrypt.h
@@ -0,0 +1,49 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright (C) 2022-2023 Eneas Ulir de Queiroz
+ */
+
+#include <stdio.h>
+
+#define CRYPT_BUF_SIZE 1024
+
+#ifdef USE_MBEDTLS
+# include <mbedtls/cipher.h>
+
+# if defined(MBEDTLS_MAX_BLOCK_LENGTH) \
+     && MBEDTLS_MAX_BLOCK_LENGTH > CRYPT_BUF_SIZE
+#  undef CRYPT_BUF_SIZE
+#  define CRYPT_BUF_SIZE MAX_BLOCK_LENGTH
+# endif
+
+unsigned char *hexstr2buf(const char* str, long *len);
+
+#else /* USE_MBEDTLS */
+# ifdef USE_WOLFSSL
+#  include <wolfssl/options.h>
+#  include <wolfssl/openssl/evp.h>
+# else
+#  include <openssl/evp.h>
+# endif
+
+# if defined(EVP_MAX_BLOCK_LENGTH) \
+     && EVP_MAX_BLOCK_LENGTH > CRYPT_BUF_SIZE
+#  undef CRYPT_BUF_SIZE
+#  define CRYPT_BUF_SIZE EVP_MAX_BLOCK_LENGTH
+# endif
+
+# define hexstr2buf OPENSSL_hexstr2buf
+
+#endif /* USE_MBEDTLS */
+
+typedef void cipher_t;
+typedef void ctx_t;
+
+const cipher_t *get_default_cipher(void);
+const cipher_t *get_cipher_or_print_error(char *name);
+int get_cipher_ivsize(const cipher_t *cipher);
+int get_cipher_keysize(const cipher_t *cipher);
+
+ctx_t *create_ctx(const cipher_t *cipher, const unsigned char *key,
+		  const unsigned char *iv, int enc, int padding);
+int do_crypt(FILE *infile, FILE *outfile, ctx_t *ctx);
+void free_ctx(ctx_t *ctx);
diff --git a/package/utils/ugps/Makefile b/package/utils/ugps/Makefile
new file mode 100644
index 0000000..aa91b60
--- /dev/null
+++ b/package/utils/ugps/Makefile
@@ -0,0 +1,45 @@
+#
+# Copyright (C) 2014 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=ugps
+PKG_RELEASE:=1
+
+PKG_SOURCE_URL=$(PROJECT_GIT)/project/ugps.git
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_DATE:=2024-02-14
+PKG_SOURCE_VERSION:=69561a074d6f50f63b82608b19041e5eb2c605a9
+PKG_MIRROR_HASH:=87f9634c5e940523808391886fde504237ac2f7f62224733120a06fba4f7e952
+
+PKG_MAINTAINER:=John Crispin <john@phrozen.org>
+PKG_LICENSE:=GPL-2.0+
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/cmake.mk
+
+define Package/ugps
+  SECTION:=utils
+  CATEGORY:=Utilities
+  TITLE:=OpenWrt GPS Daemon
+  DEPENDS:=+libubox +libubus
+endef
+
+TARGET_CFLAGS += -I$(STAGING_DIR)/usr/include
+
+define Package/ugps/conffiles
+/etc/config/gps
+endef
+
+define Package/ugps/install
+	$(INSTALL_DIR) $(1)/usr/sbin $(1)/etc/init.d $(1)/etc/config
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/ugps $(1)/usr/sbin/
+	$(INSTALL_BIN) ./files/ugps.init $(1)/etc/init.d/ugps
+	$(INSTALL_CONF) ./files/gps.config $(1)/etc/config/gps
+endef
+
+$(eval $(call BuildPackage,ugps))
diff --git a/package/utils/ugps/files/gps.config b/package/utils/ugps/files/gps.config
new file mode 100644
index 0000000..01559f7
--- /dev/null
+++ b/package/utils/ugps/files/gps.config
@@ -0,0 +1,4 @@
+config gps
+	option	'tty'	'ttyACM0'
+	option	'adjust_time'	'1'
+	option	'disabled'	'1'
diff --git a/package/utils/ugps/files/ugps.init b/package/utils/ugps/files/ugps.init
new file mode 100644
index 0000000..e702b4c
--- /dev/null
+++ b/package/utils/ugps/files/ugps.init
@@ -0,0 +1,38 @@
+#!/bin/sh /etc/rc.common
+# Copyright (c) 2014 OpenWrt.org
+
+START=80
+
+USE_PROCD=1
+PROG=/usr/sbin/ugps
+
+service_triggers() {
+	procd_add_reload_trigger gps
+}
+
+start_service() {
+	local tty="$(uci get gps.@gps[-1].tty)"
+	local baudrate="$(uci get gps.@gps[-1].baudrate || echo 0)"
+	local atime="$(uci get gps.@gps[-1].adjust_time)"
+	local disabled="$(uci get gps.@gps[-1].disabled || echo 0)"
+
+	[ "$disabled" == "0" ] || return
+	[ "$tty" ] || return
+
+	case "$tty" in
+		"/"*)
+			true
+			;;
+		*)
+			tty="/dev/$tty"
+			;;
+	esac
+
+	procd_open_instance
+	procd_set_param command "$PROG"
+	[ "$baudrate" -eq 0 ] || procd_append_param command "-b ${baudrate}"
+	[ "$atime" -eq 0 ] || procd_append_param command "-a"
+	procd_append_param command "$tty"
+	procd_set_param respawn
+	procd_close_instance
+}
diff --git a/package/utils/usbgadget/Makefile b/package/utils/usbgadget/Makefile
new file mode 100644
index 0000000..d3a68ea
--- /dev/null
+++ b/package/utils/usbgadget/Makefile
@@ -0,0 +1,54 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=usbgadget
+PKG_RELEASE:=1
+
+PKG_LICENSE:=BSD-2-Clause
+
+PKG_MAINTAINER:=Chuanhong Guo <gch981213@gmail.com>
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/$(PKG_NAME)
+  SECTION:=utils
+  CATEGORY:=Utilities
+  DEPENDS:=@USB_GADGET_SUPPORT +kmod-usb-gadget +kmod-usb-lib-composite
+  TITLE:=init script to create USB gadgets
+endef
+
+define Build/Compile
+endef
+
+define Package/$(PKG_NAME)/install
+	$(INSTALL_DIR) $(1)/etc/config $(1)/etc/init.d
+	$(INSTALL_CONF) ./files/usbgadget.conf $(1)/etc/config/usbgadget
+	$(INSTALL_BIN) ./files/usbgadget.init $(1)/etc/init.d/usbgadget
+endef
+
+$(eval $(call BuildPackage,$(PKG_NAME)))
+
+# 1: short name
+# 2: description
+# 3: dependencies on other packages
+define GadgetPreset
+  define Package/$(PKG_NAME)-$(1)
+    SECTION:=utils
+    CATEGORY:=Utilities
+    TITLE+= $(2) gadget preset
+    DEPENDS+= $(3)
+  endef
+
+  define Package/$(PKG_NAME)-$(1)/description
+   This package contains the USB gadget preset for $(3).
+  endef
+
+  define Package/$(PKG_NAME)-$(1)/install
+	$(INSTALL_DIR) $$(1)/usr/share/usbgadget
+	$(INSTALL_CONF) ./files/presets/$(1) $$(1)/usr/share/usbgadget
+  endef
+
+  $$(eval $$(call BuildPackage,$(PKG_NAME)-$(1)))
+endef
+
+$(eval $(call GadgetPreset,ncm,CDC-NCM,+kmod-usb-gadget-ncm))
+$(eval $(call GadgetPreset,acm,CDC-ACM,+kmod-usb-gadget-serial))
\ No newline at end of file
diff --git a/package/utils/usbgadget/files/presets/acm b/package/utils/usbgadget/files/presets/acm
new file mode 100644
index 0000000..f8ce9c4
--- /dev/null
+++ b/package/utils/usbgadget/files/presets/acm
@@ -0,0 +1,13 @@
+config gadget 'g1'
+	option idVendor '0x0525'
+	option idProduct '0xa4a7'
+	option bDeviceClass '2'
+	option product 'Gadget Serial v2.4'
+
+config configuration 'cfg1'
+	option configuration 'ACM'
+	option gadget 'g1'
+
+config function 'acm1'
+	option function 'acm'
+	option configuration 'cfg1'
diff --git a/package/utils/usbgadget/files/presets/ncm b/package/utils/usbgadget/files/presets/ncm
new file mode 100644
index 0000000..cb3a193
--- /dev/null
+++ b/package/utils/usbgadget/files/presets/ncm
@@ -0,0 +1,13 @@
+config gadget 'g1'
+	option idVendor '0x0525'
+	option idProduct '0xa4a1'
+	option bDeviceClass '2'
+	option product 'NCM Gadget'
+
+config configuration 'cfg1'
+	option configuration 'NCM'
+	option gadget 'g1'
+
+config function 'ncm1'
+	option function 'ncm'
+	option configuration 'cfg1'
diff --git a/package/utils/usbgadget/files/usbgadget.conf b/package/utils/usbgadget/files/usbgadget.conf
new file mode 100644
index 0000000..0d80fc9
--- /dev/null
+++ b/package/utils/usbgadget/files/usbgadget.conf
@@ -0,0 +1,12 @@
+# apply a preset under /usr/share/usbgadget
+config preset
+	option name 'ncm'
+	# specify a UDC to enable this gadget:
+	# option UDC 'musb-hdrc.2.auto'
+
+# or create a custom gadget here following the content of presets:
+#config gadget 'g1'
+#	option idVendor ...
+#	...
+# and add an UDC under the gadget section to enable it:
+#	option UDC 'musb-hdrc.2.auto'
diff --git a/package/utils/usbgadget/files/usbgadget.init b/package/utils/usbgadget/files/usbgadget.init
new file mode 100644
index 0000000..f2e105c
--- /dev/null
+++ b/package/utils/usbgadget/files/usbgadget.init
@@ -0,0 +1,144 @@
+#!/bin/sh /etc/rc.common
+
+START=19
+
+GADGET_FS=/sys/kernel/config/usb_gadget
+GADGET_PRESETS_DIR=/usr/share/usbgadget
+GADGET_PREFIX=owrt_
+
+log() {
+	logger -t usbgadget "$@"
+}
+
+apply_configs() {
+	local fs_path="$1"
+	local cfg="$2"
+	for param in $(find "$fs_path" -maxdepth 1 -type f -exec basename '{}' ';'); do
+		[ "$param" = "UDC" ] && continue
+
+		config_get val "$cfg" "$param"
+		[ -n "$val" ] && echo "$val" > "${fs_path}/${param}"
+	done
+}
+
+setup_gadget() {
+	local cfg="$1"
+	local gadget_path="${GADGET_FS}/${GADGET_PREFIX}${cfg}"
+	local param udc
+
+	config_get udc "$cfg" UDC
+	[ -z "$udc" ] && return
+
+	mkdir "$gadget_path" || return
+	apply_configs "$gadget_path" "$cfg"
+
+	local strings_path="${gadget_path}/strings/0x409"
+	mkdir "$strings_path"
+	apply_configs "$strings_path" "$cfg"
+}
+
+setup_configuration() {
+	local cfg="$1"
+	local gadget
+	config_get gadget "$cfg" gadget
+	local cfgs_path="${GADGET_FS}/${GADGET_PREFIX}${gadget}/configs"
+	[ -d "${cfgs_path}" ] || return
+	local cfg_path="${cfgs_path}/${cfg}.1"
+	mkdir "$cfg_path" || {
+		log "failed to create configuration ${cfg}"
+		return
+	}
+
+	apply_configs "$cfg_path" "$cfg"
+
+	local strings_path="${cfg_path}/strings/0x409"
+	mkdir "$strings_path"
+	apply_configs "$strings_path" "$cfg"
+}
+
+setup_function() {
+	local cfg="$1"
+	local usbcfg gadget usbfun
+
+	config_get usbcfg "$cfg" configuration
+	[ -z "$usbcfg" ] && return
+	config_get usbfun "$cfg" function
+	[ -z "$usbfun" ] && return
+
+	config_get gadget "$usbcfg" gadget
+	local gadget_path="${GADGET_FS}/${GADGET_PREFIX}${gadget}"
+	local cfg_path="${gadget_path}/configs/${usbcfg}.1"
+	[ -d "${cfg_path}" ] || return
+
+	local fun_path="${gadget_path}/functions/${usbfun}.${cfg}"
+	mkdir "$fun_path" || {
+		log "failed to create function ${usbfun}.${cfg}"
+		return
+	}
+
+	apply_configs "$fun_path" "$cfg"
+
+	ln -s "$fun_path" "$cfg_path"
+}
+
+attach_gadget() {
+	local cfg="$1"
+	local gadget_path="${GADGET_FS}/${GADGET_PREFIX}${cfg}"
+	local param udc
+
+	config_get udc "$cfg" UDC
+	[ -z "$udc" ] && return
+
+	echo "$udc" > "$gadget_path/UDC"
+}
+
+load_gadget() {
+	config_foreach setup_gadget gadget
+	config_foreach setup_configuration configuration
+	config_foreach setup_function function
+	config_foreach attach_gadget gadget
+}
+
+# use subshell for isolated env
+apply_preset() (
+	local preset="$1"
+	local gadget="$2"
+	UCI_CONFIG_DIR=$GADGET_PRESETS_DIR config_load "$1"
+	config_set g1 UDC "$2"
+	load_gadget
+)
+
+load_preset() {
+	local cfg="$1"
+	config_get name "$cfg" name
+	config_get udc "$cfg" UDC
+	[ -z "$udc" ] && return
+	apply_preset $name $udc
+}
+
+start() {
+	grep -q /sys/kernel/config /proc/mounts || \
+		mount -t configfs configfs /sys/kernel/config
+
+	[ -d /sys/kernel/config/usb_gadget ] || {
+		log "usb_gadget support not found."
+		return 1
+	}
+
+	config_load usbgadget
+	config_foreach load_preset preset
+	load_gadget
+}
+
+stop() {
+	for gadget_path in ${GADGET_FS}/${GADGET_PREFIX}* ; do
+		[ -d "$gadget_path" ] || continue
+		echo "" > ${gadget_path}/UDC
+		find ${gadget_path}/configs -maxdepth 2 -type l -exec rm '{}' ';'
+		rmdir ${gadget_path}/configs/*/strings/*
+		rmdir ${gadget_path}/configs/*
+		rmdir ${gadget_path}/functions/*
+		rmdir ${gadget_path}/strings/*
+		rmdir $gadget_path
+	done
+}
diff --git a/package/utils/usbmode/Makefile b/package/utils/usbmode/Makefile
new file mode 100644
index 0000000..33362d3
--- /dev/null
+++ b/package/utils/usbmode/Makefile
@@ -0,0 +1,74 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=usbmode
+PKG_RELEASE:=1
+
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_URL=$(PROJECT_GIT)/project/usbmode.git
+PKG_SOURCE_DATE:=2022-02-24
+PKG_SOURCE_VERSION:=3c8595a4e75510f58fa231b145d5506768dcafc9
+PKG_MIRROR_HASH:=e8a40ed3b849c3b9ba9c9823a4631731dcf261d3529f173ff5973f7cc08add15
+CMAKE_INSTALL:=1
+
+PKG_LICENSE:=GPL-2.0
+PKG_LICENSE_FILES:=
+
+PKG_MAINTAINER:=Felix Fietkau <nbd@nbd.name>
+
+PKG_DATA_VERSION:=20191128
+PKG_DATA_URL:=http://www.draisberghof.de/usb_modeswitch
+PKG_DATA_PATH:=usb-modeswitch-data-$(PKG_DATA_VERSION)
+PKG_DATA_FILENAME:=$(PKG_DATA_PATH).tar.bz2
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/cmake.mk
+
+define Download/data
+  FILE:=$(PKG_DATA_FILENAME)
+  URL:=$(PKG_DATA_URL)
+  HASH:=3f039b60791c21c7cb15c7986cac89650f076dc274798fa242231b910785eaf9
+endef
+$(eval $(call Download,data))
+
+define Package/usb-modeswitch
+  SECTION:=utils
+  CATEGORY:=Utilities
+  DEPENDS:=+libubox +libblobmsg-json +libusb-1.0
+  TITLE:=USB mode switching utility
+endef
+
+define Build/Prepare
+	$(Build/Prepare/Default)
+	tar xvfj $(DL_DIR)/$(PKG_DATA_FILENAME) -C $(PKG_BUILD_DIR)
+	#remove devices with unsupported modes
+	for filevar in $(PKG_BUILD_DIR)/$(PKG_DATA_PATH)/usb_modeswitch.d/* ; \
+	do \
+		if grep -q -E '(Quanta|Option|Blackberry|Pantech)Mode' "$$$$filevar" ; then \
+			rm "$$$$filevar" ; \
+		fi \
+	done
+	cp ./data/* $(PKG_BUILD_DIR)/$(PKG_DATA_PATH)/usb_modeswitch.d/
+	#in order to keep the Lede GIT repo free of filenames with colons,
+	#we name the files xxxx-yyyy
+	# and rename here after copying to the build directory
+	for filevar in $(PKG_BUILD_DIR)/$(PKG_DATA_PATH)/usb_modeswitch.d/*-* ; \
+	do \
+		[ -f "$$$$filevar" ] || continue ; \
+		FILENAME=$$$$(basename $$$$filevar) ; \
+		NEWNAME=$$$${FILENAME//-/:} ; \
+		rm "$(PKG_BUILD_DIR)/$(PKG_DATA_PATH)/usb_modeswitch.d/$$$$NEWNAME" ; \
+		mv "$(PKG_BUILD_DIR)/$(PKG_DATA_PATH)/usb_modeswitch.d/$$$$FILENAME" "$(PKG_BUILD_DIR)/$(PKG_DATA_PATH)/usb_modeswitch.d/$$$$NEWNAME" ; \
+	done
+endef
+
+define Package/usb-modeswitch/install
+	$(INSTALL_DIR) $(1)/etc/hotplug.d/usb $(1)/etc/init.d $(1)/sbin
+	perl $(PKG_BUILD_DIR)/convert-modeswitch.pl \
+		$(PKG_BUILD_DIR)/$(PKG_DATA_PATH)/usb_modeswitch.d/* \
+		> $(1)/etc/usb-mode.json
+	$(INSTALL_CONF) ./files/usbmode.hotplug $(1)/etc/hotplug.d/usb/20-usb_mode
+	$(INSTALL_BIN) ./files/usbmode.init $(1)/etc/init.d/usbmode
+	$(CP) $(PKG_INSTALL_DIR)/usr/sbin/usbmode $(1)/sbin/
+endef
+
+$(eval $(call BuildPackage,usb-modeswitch))
diff --git a/package/utils/usbmode/data/12d1-1f16 b/package/utils/usbmode/data/12d1-1f16
new file mode 100644
index 0000000..beda01f
--- /dev/null
+++ b/package/utils/usbmode/data/12d1-1f16
@@ -0,0 +1,2 @@
+# Vodafone K5150
+MBIM=1
diff --git a/package/utils/usbmode/data/3426-1f01 b/package/utils/usbmode/data/3426-1f01
new file mode 100644
index 0000000..cd5b7e7
--- /dev/null
+++ b/package/utils/usbmode/data/3426-1f01
@@ -0,0 +1,4 @@
+# Huawei E5785
+TargetVendor=0x3426
+TargetProduct=0x14db
+HuaweiNewMode=1
diff --git a/package/utils/usbmode/files/usbmode.hotplug b/package/utils/usbmode/files/usbmode.hotplug
new file mode 100644
index 0000000..b238894
--- /dev/null
+++ b/package/utils/usbmode/files/usbmode.hotplug
@@ -0,0 +1 @@
+/etc/init.d/usbmode start
diff --git a/package/utils/usbmode/files/usbmode.init b/package/utils/usbmode/files/usbmode.init
new file mode 100755
index 0000000..43e8ec5
--- /dev/null
+++ b/package/utils/usbmode/files/usbmode.init
@@ -0,0 +1,12 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2013 OpenWrt.org
+
+START=20
+USE_PROCD=1
+
+start_service()
+{
+	procd_open_instance
+	procd_set_param command "/sbin/usbmode" -s
+	procd_close_instance
+}
diff --git a/package/utils/util-linux/Makefile b/package/utils/util-linux/Makefile
new file mode 100644
index 0000000..83f3a8c
--- /dev/null
+++ b/package/utils/util-linux/Makefile
@@ -0,0 +1,954 @@
+#
+# Copyright (C) 2007-2018 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=util-linux
+PKG_VERSION:=2.40.2
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=@KERNEL/linux/utils/$(PKG_NAME)/v2.40
+PKG_HASH:=d78b37a66f5922d70edf3bdfb01a6b33d34ed3c3cafd6628203b2a2b67c8e8b3
+PKG_CPE_ID:=cpe:/a:kernel:util-linux
+
+PKG_LICENSE:=GPL-2.0-only
+PKG_LICENSE_FILES:=	COPYING					\
+			libblkid/COPYING			\
+			libmount/COPYING			\
+			Documentation/licenses/COPYING.GPLv2	\
+			Documentation/licenses/COPYING.LGPLv2.1	\
+			libuuid/COPYING				\
+			Documentation/licenses/COPYING.BSD-3
+
+PKG_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/meson.mk
+
+define Package/util-linux/Default
+  SECTION:=utils
+  CATEGORY:=Utilities
+  DEPENDS:= +librt
+  URL:=http://www.kernel.org/pub/linux/utils/util-linux/
+endef
+
+define Package/libblkid
+$(call Package/util-linux/Default)
+  DEPENDS:=+libuuid
+  TITLE:=block device id library
+  SECTION:=libs
+  CATEGORY:=Libraries
+  ABI_VERSION:=1
+endef
+
+define Package/libblkid/description
+ The libblkid library is used to identify block devices (disks) as to their
+ content (e.g. filesystem type, partitions) as well as extracting additional
+ information such as filesystem labels/volume names, partitions, unique
+ identifiers/serial numbers...
+endef
+
+define Package/libfdisk
+$(call Package/util-linux/Default)
+  DEPENDS:=+libuuid +libblkid
+  TITLE:=partition manipulating library
+  SECTION:=libs
+  CATEGORY:=Libraries
+  ABI_VERSION:=1
+endef
+
+define Package/libfdisk/description
+  The libfdisk library is used for manipulating with partition tables.
+endef
+
+define Package/libmount
+$(call Package/util-linux/Default)
+  DEPENDS:=+libblkid
+  TITLE:=mount library
+  SECTION:=libs
+  CATEGORY:=Libraries
+  ABI_VERSION:=1
+endef
+
+define Package/libmount/description
+ The libmount library is used to parse /etc/fstab, /etc/mtab and
+ /proc/self/mountinfo files, manage the mtab file, evaluate mount options...
+endef
+
+define Package/libuuid
+$(call Package/util-linux/Default)
+  TITLE:=DCE compatible Universally Unique Identifier library
+  SECTION:=libs
+  CATEGORY:=Libraries
+  ABI_VERSION:=1
+endef
+
+define Package/libuuid/description
+ The UUID library is used to generate unique identifiers for objects
+ that may be accessible beyond the local system. This library
+ generates UUIDs compatible with those created by the Open Software
+ Foundation (OSF) Distributed Computing Environment (DCE) utility.
+endef
+
+define Package/libsmartcols
+$(call Package/util-linux/Default)
+  TITLE:=table or tree library
+  SECTION:=libs
+  CATEGORY:=Libraries
+  ABI_VERSION:=1
+endef
+
+define Package/libsmartcols/description
+ The smartcols library is used to print tables and trees in a pretty way.
+endef
+
+define Package/agetty
+$(call Package/util-linux/Default)
+  TITLE:=alternative Linux getty
+  SUBMENU=Terminal
+endef
+
+define Package/agetty/description
+ agetty opens a tty port, prompts for a login name and invokes the
+ /bin/login command
+endef
+
+define Package/blkdiscard
+$(call Package/util-linux/Default)
+  TITLE:=discard sectors on a device
+  SUBMENU=Disc
+  DEPENDS:=libblkid
+endef
+
+define Package/blkdiscard/description
+ The blkdiscard is used to discard device sectors. This is useful for
+ solid-state drivers (SSDs) and thinly-provisioned storage. Unlike fstrim,
+ this command is used directly on the block device.
+endef
+
+define Package/blkid
+$(call Package/util-linux/Default)
+  TITLE:=locate and print block device attributes
+  DEPENDS:= +libblkid +libuuid
+  SUBMENU=Disc
+endef
+
+define Package/blkid/description
+ The blkid program is the command-line interface to working with the libblkid
+ library.
+endef
+
+define Package/blockdev
+$(call Package/util-linux/Default)
+  TITLE:=call block device ioctls from the command line
+  SUBMENU=Disc
+endef
+
+define Package/blockdev/description
+ The blockdev program is the command-line interface to call block device ioctls.
+endef
+
+define Package/cal
+$(call Package/util-linux/Default)
+  TITLE:=display a calendar
+  DEPENDS:= +libncurses
+endef
+
+define Package/cal/description
+ cal displays a simple calendar
+endef
+
+define Package/cfdisk
+$(call Package/util-linux/Default)
+  TITLE:=display or manipulate disk partition table
+  DEPENDS:= +libblkid +libncurses +libsmartcols +libfdisk +libmount
+  SUBMENU:=Disc
+endef
+
+define Package/cfdisk/description
+ cfdisk is a curses-based program for partitioning any hard disk drive
+endef
+
+define Package/colrm
+$(call Package/util-linux/Default)
+  TITLE:=colrm removes selected columns from a file
+  DEPENDS:=
+endef
+
+define Package/colrm/description
+ colrm removes selected columns from a file. Input is taken from
+ standard input. Output is sent to standard output.
+endef
+
+define Package/dmesg
+$(call Package/util-linux/Default)
+  TITLE:=print or control the kernel ring buffer
+  DEPENDS:= +libncursesw
+endef
+
+define Package/dmesg/description
+ dmesg  is used to examine or control the kernel ring buffer
+endef
+
+define Package/eject
+$(call Package/util-linux/Default)
+  TITLE:=eject removable media
+  DEPENDS:= +libblkid +libmount +libuuid
+  SUBMENU=Disc
+endef
+
+define Package/eject/description
+  eject allows removable media (typically a CD-ROM, floppy disk, tape, or JAZ
+  or ZIP disk) to be ejected under software control.
+endef
+
+define Package/fdisk
+$(call Package/util-linux/Default)
+  TITLE:=manipulate disk partition table
+  DEPENDS:= +libblkid +libsmartcols +libfdisk +libncursesw
+  SUBMENU=Disc
+endef
+
+define Package/fdisk/description
+ a menu-driven program for creation and manipulation of partition tables
+endef
+
+define Package/findfs
+$(call Package/util-linux/Default)
+  TITLE:=find a filesystem by label or UUID
+  DEPENDS:= +libblkid
+  SUBMENU=Disc
+endef
+
+define Package/findfs/description
+ findfs will search the disks in the system looking for a filesystem which has
+ a label matching label or a UUID equal to uuid
+endef
+
+define Package/flock
+$(call Package/util-linux/Default)
+  TITLE:=manage locks from shell scripts
+  ALTERNATIVES:=200:/usr/bin/flock:/usr/bin/util-linux-flock
+endef
+
+define Package/flock/description
+  manages flock locks from within shell scripts or the command line
+endef
+
+define Package/fstrim
+$(call Package/util-linux/Default)
+  TITLE:=discard unused blocks on a mounted filesystem
+  DEPENDS:= +libblkid +libuuid +libsmartcols +libmount
+  SUBMENU=Filesystem
+endef
+
+define Package/fstrim/description
+  fstrim is used on a mounted filesystem to discard (or "trim") blocks
+  which are not in use by the filesystem.  This is useful for solid-
+  state drives (SSDs) and thinly-provisioned storage.
+endef
+
+define Package/getopt
+$(call Package/util-linux/Default)
+  TITLE:=parse command options (enhanced)
+endef
+
+define Package/getopt/description
+ getopt is used to break up (parse) options in command lines for easy parsing
+ by shell procedures, and to check for legal options
+endef
+
+define Package/hwclock
+$(call Package/util-linux/Default)
+  TITLE:=query or set the hardware clock
+endef
+
+define Package/hwclock/description
+ hwclock is a tool for accessing the Hardware Clock
+endef
+
+define Package/ipcs
+$(call Package/util-linux/Default)
+  TITLE:=show information on IPC facilities
+endef
+
+define Package/ipcs/description
+  ipcs shows information on the inter-process communication facilities for
+  which the calling process has read access. By default it shows information
+  about all three resources: shared memory segments, message queues, and
+  semaphore arrays.
+endef
+
+define Package/logger
+$(call Package/util-linux/Default)
+  TITLE:=a shell command interface to the syslog system log module
+  ALTERNATIVES:=200:/usr/bin/logger:/usr/bin/util-linux-logger
+endef
+
+define Package/logger/description
+ logger makes entries in the system log, it provides a shell command interface
+ to the syslog system log module
+endef
+
+define Package/look
+$(call Package/util-linux/Default)
+  TITLE:=display lines beginning with a given string
+endef
+
+define Package/look/description
+ look utility displays any lines in file which contain string
+endef
+
+define Package/losetup
+$(call Package/util-linux/Default)
+  TITLE:=set up and control loop devices
+  DEPENDS:= +libsmartcols
+endef
+
+define Package/losetup/description
+ losetup is used to associate loop devices with regular files or block devices,
+ to detach loop devices and to query the status of a loop device
+endef
+
+define Package/lsblk
+$(call Package/util-linux/Default)
+  TITLE:=list block devices
+  DEPENDS:= +libblkid +libmount +libsmartcols +libncurses
+  SUBMENU=Disc
+endef
+
+define Package/lsblk/description
+ lsblk lists information about all or the specified block devices
+endef
+
+define Package/lscpu
+$(call Package/util-linux/Default)
+  TITLE:=display information about the CPU architecture
+  DEPENDS:= +libsmartcols
+endef
+
+define Package/lscpu/description
+ lscpu displays information about the CPU architecture
+endef
+
+define Package/lslocks
+$(call Package/util-linux/Default)
+  TITLE:=list local system locks
+  DEPENDS:= +libmount +libsmartcols
+endef
+
+define Package/lslocks/description
+ lslocks lists information about all the currently held file locks in a Linux system
+endef
+
+define Package/lsns
+$(call Package/util-linux/Default)
+  TITLE:=list system namespaces
+  DEPENDS:= +libblkid +libmount +libsmartcols
+endef
+
+define Package/lsns/description
+ lsns lists information about all namespaces and their processes
+endef
+
+define Package/more
+$(call Package/util-linux/Default)
+  TITLE:=filter for paging through text one screenful at a time
+  DEPENDS:= +libncurses
+endef
+
+define Package/more/description
+ more is a filter for paging through text one screenful at a time
+endef
+
+define Package/mcookie
+$(call Package/util-linux/Default)
+  TITLE:=generate magic cookies for xauth
+endef
+
+define Package/mcookie/description
+ mcookie generates a 128-bit random hexadecimal number for use with the X
+ authority system
+endef
+
+define Package/mount-utils
+$(call Package/util-linux/Default)
+  TITLE:=related (u)mount utilities
+  DEPENDS+= +libmount +libsmartcols
+endef
+
+define Package/mount-utils/description
+ contains: mount, umount, findmnt
+endef
+
+define Package/namei
+$(call Package/util-linux/Default)
+  TITLE:=follow a pathname until a terminal point is found
+endef
+
+define Package/namei/description
+ namei uses its arguments as pathnames to any type of Unix file (symlinks,
+ files, directories, and so forth)
+endef
+
+define Package/nsenter
+$(call Package/util-linux/Default)
+  TITLE:=enter a namespace
+endef
+
+define Package/nsenter/description
+  run program with namespaces of other processes
+endef
+
+define Package/prlimit
+$(call Package/util-linux/Default)
+  TITLE:=get and set process resource limits
+  DEPENDS:= +libsmartcols
+endef
+
+define Package/prlimit/description
+  Given a process id and one or more resources, prlimit tries to retrieve
+  and/or modify the limits.
+endef
+
+define Package/rename
+$(call Package/util-linux/Default)
+  TITLE:=rename files
+endef
+
+define Package/rename/description
+ rename will rename the specified files by replacing the first occurrence of
+ expression in their name by replacement
+endef
+
+define Package/rev
+$(call Package/util-linux/Default)
+  TITLE:=Reverse lines characterwise
+endef
+
+define Package/rev/description
+ rev utility copies the specified files to the standard output, reversing the
+ order of characters in every line. If no files are specified, the standard
+ input is read.
+endef
+
+define Package/partx-utils
+$(call Package/util-linux/Default)
+  TITLE:=inform kernel about the presence and numbering of on-disk partitions
+  DEPENDS:= +libblkid +libsmartcols
+  SUBMENU=Disc
+endef
+
+define Package/partx-utils/description
+ contains partx, addpart, delpart
+endef
+
+define Package/script-utils
+$(call Package/util-linux/Default)
+  TITLE:=make and replay typescript of terminal session
+  SUBMENU=Terminal
+endef
+
+define Package/script-utils/description
+ contains: script, scriptreplay
+endef
+
+define Package/setterm
+$(call Package/util-linux/Default)
+  TITLE:=set terminal attributes
+  DEPENDS:= +libncurses
+  SUBMENU:=Terminal
+endef
+
+define Package/setterm/description
+ setterm writes to standard output a character string that will invoke the
+ specified terminal capabilities
+endef
+
+define Package/sfdisk
+$(call Package/util-linux/Default)
+  TITLE:=partition table manipulator for Linux
+  SUBMENU=Disc
+  DEPENDS:= +libblkid +libfdisk +libsmartcols +libncursesw
+endef
+
+define Package/sfdisk/description
+ list the size of a partition, list the partitions on a device, check the
+ partitions on a device and repartition a device
+endef
+
+define Package/swap-utils
+$(call Package/util-linux/Default)
+  TITLE:=swap space management utilities
+  DEPENDS+= +libblkid
+  SUBMENU:=Filesystem
+endef
+
+define Package/swap-utils/description
+ contains: mkswap, swaplabel
+endef
+
+define Package/taskset
+$(call Package/util-linux/Default)
+  TITLE:=set or retrieve a process's CPU affinity
+  ALTERNATIVES:=200:/usr/bin/taskset:/usr/bin/util-linux-taskset
+endef
+
+define Package/taskset/description
+ contains: taskset
+endef
+
+define Package/unshare
+$(call Package/util-linux/Default)
+  TITLE:=unshare userspace tool
+endef
+
+define Package/unshare/description
+  run programs with some namespaces unshared from parent
+endef
+
+define Package/uuidd
+$(call Package/util-linux/Default)
+  TITLE:=UUID generation daemon
+  DEPENDS:= +libuuid
+endef
+
+define Package/uuidd/description
+ The uuidd daemon is used by the UUID library to generate universally unique
+ identifiers (UUIDs), especially time-based UUIDs, in a secure and
+ guaranteed-unique fashion, even in the face of large numbers of threads
+ running on different CPUs trying to grab UUIDs.
+endef
+
+define Package/uuidgen
+$(call Package/util-linux/Default)
+  TITLE:=create a new UUID value
+  DEPENDS:= +libuuid
+endef
+
+define Package/uuidgen/description
+ The uuidgen program creates (and prints) a new universally unique identifier
+ (UUID) using the libuuid library. The new UUID can reasonably be considered
+ unique among all UUIDs created on the local system, and among UUIDs created on
+ other systems in the past and in the future.
+endef
+
+define Package/wall
+$(call Package/util-linux/Default)
+  TITLE:=send a message to everybody's terminal
+  SUBMENU=Terminal
+endef
+
+define Package/wall/description
+ wall sends a message to everybody logged in with their mesg permission
+ set to yes
+endef
+
+define Package/whereis
+$(call Package/util-linux/Default)
+  TITLE:=locate the binary, source, and manual page files for a command
+endef
+
+define Package/whereis/description
+ whereis locates source/binary and manuals sections for specified files
+endef
+
+define Package/wipefs
+$(call Package/util-linux/Default)
+  TITLE:=wipe a signature from a device
+  DEPENDS:= +libblkid +libsmartcols
+  SUBMENU:=Disc
+endef
+
+define Package/wipefs/description
+ wipefs can erase filesystem, raid or partition table signatures (magic
+ strings) from the specified device to make the signature invisible for
+ libblkid.
+endef
+
+MESON_ARGS += \
+	-Dsystemd=disabled \
+	-Dtinfo=disabled \
+	-Dcryptsetup=disabled \
+	-Dlibutil=disabled \
+	-Dlibutempter=disabled \
+	-Dlibpcre2-posix=disabled \
+	-Dlibuser=disabled \
+	-Duse-tty-group=false \
+	-Duse-tls=false \
+	-Dbuild-python=disabled \
+	-Dbuild-zramctl=disabled \
+	-Dbuild-fsck=disabled \
+	-Dbuild-wipefs=disabled \
+	-Dbuild-fallocate=disabled \
+	-Dbuild-setpriv=disabled \
+	-Dbuild-hardlink=disabled \
+	-Dbuild-cramfs=disabled \
+	-Dbuild-bfs=disabled \
+	-Dbuild-minix=disabled \
+	-Dbuild-fdformat=disabled \
+	-Dbuild-lslogins=disabled \
+	-Dbuild-wdctl=disabled \
+	-Dbuild-cal=disabled \
+	-Dbuild-switch_root=disabled \
+	-Dbuild-pivot_root=disabled \
+	-Dbuild-lsmem=disabled \
+	-Dbuild-lsirq=disabled \
+	-Dbuild-irqtop=disabled \
+	-Dbuild-chmem=disabled \
+	-Dbuild-ipcrm=disabled \
+	-Dbuild-rfkill=disabled \
+	-Dbuild-tunelp=disabled \
+	-Dbuild-kill=disabled \
+	-Dbuild-last=disabled \
+	-Dbuild-utmpdump=disabled \
+	-Dbuild-line=disabled \
+	-Dbuild-mesg=disabled \
+	-Dbuild-raw=disabled \
+	-Dbuild-vipw=disabled \
+	-Dbuild-newgrp=disabled \
+	-Dbuild-chfn-chsh=disabled \
+	-Dbuild-login=disabled \
+	-Dbuild-nologin=disabled \
+	-Dbuild-sulogin=disabled \
+	-Dbuild-su=disabled \
+	-Dbuild-runuser=disabled \
+	-Dbuild-ul=disabled \
+	-Dbuild-pg=disabled \
+	-Dbuild-write=disabled \
+	-Dbuild-bash-completion=disabled \
+	-Dbuild-pylibmount=disabled \
+	-Dbuild-liblastlog2=disabled \
+	-Dreadline=disabled \
+	-Dmagic=disabled \
+	-Dncursesw=enabled
+
+define Build/InstallDev
+	$(INSTALL_DIR) $(1)/usr/lib/pkgconfig
+	$(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/blkid.pc $(1)/usr/lib/pkgconfig
+	$(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/fdisk.pc $(1)/usr/lib/pkgconfig
+	$(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/mount.pc $(1)/usr/lib/pkgconfig
+	$(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/smartcols.pc $(1)/usr/lib/pkgconfig
+	$(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/uuid.pc $(1)/usr/lib/pkgconfig
+
+	$(INSTALL_DIR) $(1)/usr/include/blkid
+	$(CP) $(PKG_INSTALL_DIR)/usr/include/blkid/blkid.h $(1)/usr/include/blkid
+	$(INSTALL_DIR) $(1)/usr/include/libfdisk
+	$(CP) $(PKG_INSTALL_DIR)/usr/include/libfdisk/libfdisk.h $(1)/usr/include/libfdisk
+	$(INSTALL_DIR) $(1)/usr/include/libmount
+	$(CP) $(PKG_INSTALL_DIR)/usr/include/libmount/libmount.h $(1)/usr/include/libmount
+	$(INSTALL_DIR) $(1)/usr/include/uuid
+	$(CP) $(PKG_INSTALL_DIR)/usr/include/uuid/uuid.h $(1)/usr/include/uuid
+	$(INSTALL_DIR) $(1)/usr/include/libsmartcols
+	$(CP) $(PKG_INSTALL_DIR)/usr/include/libsmartcols/libsmartcols.h $(1)/usr/include/libsmartcols
+
+	$(INSTALL_DIR) $(1)/usr/lib
+	$(CP) $(PKG_INSTALL_DIR)/usr/lib/libblkid.so* $(1)/usr/lib
+	$(CP) $(PKG_INSTALL_DIR)/usr/lib/libfdisk.so* $(1)/usr/lib
+	$(CP) $(PKG_INSTALL_DIR)/usr/lib/libmount.so* $(1)/usr/lib
+	$(CP) $(PKG_INSTALL_DIR)/usr/lib/libuuid.so* $(1)/usr/lib
+	$(CP) $(PKG_INSTALL_DIR)/usr/lib/libsmartcols.so* $(1)/usr/lib
+endef
+
+
+define Package/libfdisk/install
+	$(INSTALL_DIR) $(1)/usr/lib
+	$(CP) $(PKG_INSTALL_DIR)/usr/lib/libfdisk.so.* $(1)/usr/lib/
+endef
+
+define Package/libblkid/install
+	$(INSTALL_DIR) $(1)/usr/lib
+	$(CP) $(PKG_INSTALL_DIR)/usr/lib/libblkid.so.* $(1)/usr/lib/
+endef
+
+define Package/libmount/install
+	$(INSTALL_DIR) $(1)/usr/lib
+	$(CP) $(PKG_INSTALL_DIR)/usr/lib/libmount.so.* $(1)/usr/lib/
+endef
+
+define Package/libsmartcols/install
+	$(INSTALL_DIR) $(1)/usr/lib
+	$(CP) $(PKG_INSTALL_DIR)/usr/lib/libsmartcols.so.* $(1)/usr/lib/
+endef
+
+define Package/libuuid/install
+	$(INSTALL_DIR) $(1)/usr/lib
+	$(CP) $(PKG_INSTALL_DIR)/usr/lib/libuuid.so.* $(1)/usr/lib/
+endef
+
+define Package/agetty/install
+	$(INSTALL_DIR) $(1)/usr/sbin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/agetty $(1)/usr/sbin/
+endef
+
+define Package/blkdiscard/install
+	$(INSTALL_DIR) $(1)/usr/sbin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/blkdiscard $(1)/usr/sbin/
+endef
+
+define Package/blkid/install
+	$(INSTALL_DIR) $(1)/usr/sbin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/blkid $(1)/usr/sbin/
+endef
+
+define Package/blockdev/install
+	$(INSTALL_DIR) $(1)/usr/sbin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/blockdev $(1)/usr/sbin/
+endef
+
+define Package/cal/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/cal $(1)/usr/bin/
+endef
+
+define Package/cfdisk/install
+	$(INSTALL_DIR) $(1)/usr/sbin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/cfdisk $(1)/usr/sbin/
+endef
+
+define Package/colrm/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/colrm $(1)/usr/bin/
+endef
+
+define Package/dmesg/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/dmesg $(1)/usr/bin/
+endef
+
+define Package/eject/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/eject $(1)/usr/bin/
+endef
+
+define Package/fdisk/install
+	$(INSTALL_DIR) $(1)/usr/sbin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/fdisk $(1)/usr/sbin/
+endef
+
+define Package/findfs/install
+	$(INSTALL_DIR) $(1)/usr/sbin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/findfs $(1)/usr/sbin/
+endef
+
+define Package/flock/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/flock $(1)/usr/bin/util-linux-flock
+endef
+
+define Package/fstrim/install
+	$(INSTALL_DIR) $(1)/usr/sbin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/fstrim $(1)/usr/sbin/
+endef
+
+define Package/getopt/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/getopt $(1)/usr/bin/
+endef
+
+define Package/hwclock/install
+	$(INSTALL_DIR) $(1)/usr/sbin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/hwclock $(1)/usr/sbin/
+endef
+
+define Package/ipcs/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/ipcs $(1)/usr/bin/
+endef
+
+define Package/logger/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/logger $(1)/usr/bin/util-linux-logger
+endef
+
+define Package/look/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/look $(1)/usr/bin/
+endef
+
+define Package/losetup/install
+	$(INSTALL_DIR) $(1)/usr/sbin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/losetup $(1)/usr/sbin/
+endef
+
+define Package/lsblk/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/lsblk $(1)/usr/bin/
+endef
+
+define Package/lscpu/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/lscpu $(1)/usr/bin/
+endef
+
+define Package/lslocks/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/lslocks $(1)/usr/bin/
+endef
+
+define Package/lsns/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/lsns $(1)/usr/bin/
+endef
+
+define Package/more/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/more $(1)/usr/bin/
+endef
+
+define Package/mcookie/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/mcookie $(1)/usr/bin/
+endef
+
+define Package/mount-utils/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/{u,}mount $(1)/usr/bin/
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/mountpoint $(1)/usr/bin/
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/findmnt $(1)/usr/bin/
+endef
+
+define Package/namei/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/namei $(1)/usr/bin/
+endef
+
+define Package/nsenter/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/nsenter $(1)/usr/bin/
+endef
+
+define Package/prlimit/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/prlimit $(1)/usr/bin/
+endef
+
+define Package/rename/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/rename $(1)/usr/bin/
+endef
+
+define Package/rev/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/rev $(1)/usr/bin/
+endef
+
+define Package/partx-utils/install
+	$(INSTALL_DIR) $(1)/usr/sbin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/partx $(1)/usr/sbin/
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/addpart $(1)/usr/sbin/
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/delpart $(1)/usr/sbin/
+endef
+
+define Package/script-utils/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/script $(1)/usr/bin/
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/scriptreplay $(1)/usr/bin/
+endef
+
+define Package/setterm/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/setterm $(1)/usr/bin/
+endef
+
+define Package/sfdisk/install
+	$(INSTALL_DIR) $(1)/usr/sbin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/sfdisk $(1)/usr/sbin/
+endef
+
+define Package/swap-utils/install
+	$(INSTALL_DIR) $(1)/usr/sbin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/mkswap $(1)/usr/sbin/
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/swaplabel $(1)/usr/sbin/
+endef
+
+define Package/taskset/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/taskset $(1)/usr/bin/util-linux-taskset
+endef
+
+define Package/unshare/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/unshare $(1)/usr/bin/
+endef
+
+define Package/uuidd/install
+	$(INSTALL_DIR) $(1)/usr/sbin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin//uuidd $(1)/usr/sbin/
+endef
+
+define Package/uuidgen/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin//uuidgen $(1)/usr/bin/
+endef
+
+define Package/wall/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/wall $(1)/usr/bin/
+endef
+
+define Package/whereis/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/whereis $(1)/usr/bin/
+endef
+
+define Package/wipefs/install
+	$(INSTALL_DIR) $(1)/usr/sbin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/wipefs $(1)/usr/sbin/
+endef
+
+# these lines need to be ordered by dependency because of ABI versioning
+$(eval $(call BuildPackage,libuuid))
+$(eval $(call BuildPackage,libblkid))
+$(eval $(call BuildPackage,libfdisk))
+
+$(eval $(call BuildPackage,libmount))
+$(eval $(call BuildPackage,libsmartcols))
+$(eval $(call BuildPackage,agetty))
+$(eval $(call BuildPackage,blkdiscard))
+$(eval $(call BuildPackage,blkid))
+$(eval $(call BuildPackage,blockdev))
+$(eval $(call BuildPackage,cal))
+$(eval $(call BuildPackage,cfdisk))
+$(eval $(call BuildPackage,colrm))
+$(eval $(call BuildPackage,dmesg))
+$(eval $(call BuildPackage,eject))
+$(eval $(call BuildPackage,fdisk))
+$(eval $(call BuildPackage,findfs))
+$(eval $(call BuildPackage,flock))
+$(eval $(call BuildPackage,fstrim))
+$(eval $(call BuildPackage,getopt))
+$(eval $(call BuildPackage,hwclock))
+$(eval $(call BuildPackage,ipcs))
+$(eval $(call BuildPackage,logger))
+$(eval $(call BuildPackage,look))
+$(eval $(call BuildPackage,losetup))
+$(eval $(call BuildPackage,lsblk))
+$(eval $(call BuildPackage,lscpu))
+$(eval $(call BuildPackage,lslocks))
+$(eval $(call BuildPackage,lsns))
+$(eval $(call BuildPackage,more))
+$(eval $(call BuildPackage,mcookie))
+$(eval $(call BuildPackage,mount-utils))
+$(eval $(call BuildPackage,namei))
+$(eval $(call BuildPackage,nsenter))
+$(eval $(call BuildPackage,prlimit))
+$(eval $(call BuildPackage,rename))
+$(eval $(call BuildPackage,rev))
+$(eval $(call BuildPackage,partx-utils))
+$(eval $(call BuildPackage,script-utils))
+$(eval $(call BuildPackage,setterm))
+$(eval $(call BuildPackage,sfdisk))
+$(eval $(call BuildPackage,swap-utils))
+$(eval $(call BuildPackage,taskset))
+$(eval $(call BuildPackage,unshare))
+$(eval $(call BuildPackage,uuidd))
+$(eval $(call BuildPackage,uuidgen))
+$(eval $(call BuildPackage,wall))
+$(eval $(call BuildPackage,whereis))
+$(eval $(call BuildPackage,wipefs))
diff --git a/package/utils/xz/Makefile b/package/utils/xz/Makefile
new file mode 100644
index 0000000..5fb7f83
--- /dev/null
+++ b/package/utils/xz/Makefile
@@ -0,0 +1,124 @@
+#
+# Copyright (C) 2013-2015 OpenWrt.org
+# Copyright (C) 2017 Daniel Engberg <daniel.engberg.lists@pyret.net>
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=xz
+PKG_VERSION:=5.2.5
+PKG_RELEASE:=3
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=@SF/lzmautils
+PKG_HASH:=3e1e518ffc912f86608a8cb35e4bd41ad1aec210df2a47aaa1f95e7f5576ef56
+
+PKG_MAINTAINER:=
+PKG_LICENSE:=Public-Domain LGPL-2.1-or-later GPL-2.0-or-later GPL-3.0-or-later
+PKG_LICENSE_FILES:=COPYING
+PKG_CPE_ID:=cpe:/a:tukaani:xz
+
+PKG_BUILD_PARALLEL:=1
+PKG_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/xz/Default
+  SUBMENU:=Compression
+  SECTION:=utils
+  CATEGORY:=Utilities
+  URL:=https://tukaani.org/xz
+endef
+
+define Package/xz-utils
+$(call Package/xz/Default)
+  TITLE:=XZ Utils (meta)
+  MENU:=1
+endef
+
+define Package/liblzma
+$(call Package/xz/Default)
+  SECTION:=libs
+  CATEGORY:=Libraries
+  DEPENDS:=+libpthread
+  TITLE:=liblzma library from XZ Utils
+endef
+
+# $(1): package name & command in /usr/bin/
+# $(2): package dependencies
+# $(3): symbolic links to $(1) in /usr/bin/
+define BuildSubPackage
+
+  define Package/$(1)
+  $(call Package/xz/Default)
+    DEPENDS:=xz-utils $(2)
+    TITLE:=$(1) utility from XZ Utils
+    $(if $(3),ALTERNATIVES:=$(foreach f,$(1) $(3),300:/usr/bin/$(f):/usr/libexec/$(1)-lzmautils))
+  endef
+
+  define Package/$(1)/description
+   Contains: $(1) $(3)
+  endef
+
+  define Package/$(1)/install
+	$(INSTALL_DIR) $$(1)$(if $(3),/usr/libexec,/usr/bin)
+	$(CP) $(PKG_INSTALL_DIR)/usr/bin/$(1) $$(1)$(if $(3),/usr/libexec/$(1)-lzmautils,/usr/bin/$(1))
+  endef
+
+  $$(eval $$(call BuildPackage,$(1)))
+endef
+
+TARGET_LDFLAGS += -Wl,--gc-sections -flto
+
+CONFIGURE_ARGS += \
+	--enable-small \
+	--enable-assume-ram=4 \
+	--disable-assembler \
+	--disable-debug \
+	--disable-doc \
+	--disable-rpath \
+	--disable-symbol-versions \
+	--disable-werror \
+	--with-pic
+
+CONFIGURE_VARS += \
+	gl_cv_posix_shell=/bin/sh
+
+define Build/InstallDev
+	$(INSTALL_DIR) $(1)/usr/include
+	$(CP) \
+		$(PKG_INSTALL_DIR)/usr/include/lzma{,.h} \
+		$(1)/usr/include/
+	$(INSTALL_DIR) $(1)/usr/lib
+	$(CP) \
+		$(PKG_INSTALL_DIR)/usr/lib/liblzma.{a,so*} \
+		$(1)/usr/lib/
+	$(INSTALL_DIR) $(1)/usr/lib/pkgconfig
+	$(CP) \
+		$(PKG_INSTALL_DIR)/usr/lib/pkgconfig/liblzma.pc \
+		$(1)/usr/lib/pkgconfig/
+endef
+
+define Package/xz-utils/install
+	true
+endef
+
+define Package/liblzma/install
+	$(INSTALL_DIR) $(1)/usr/lib
+	$(CP) $(PKG_INSTALL_DIR)/usr/lib/liblzma.so.* $(1)/usr/lib/
+endef
+
+
+$(eval $(call BuildPackage,xz-utils))
+$(eval $(call BuildPackage,liblzma))
+$(eval $(call BuildSubPackage,lzmadec, +liblzma,))
+$(eval $(call BuildSubPackage,lzmainfo, +liblzma,))
+$(eval $(call BuildSubPackage,xz, +liblzma, lzcat lzma unlzma unxz xzcat))
+$(eval $(call BuildSubPackage,xzdec, +liblzma,))
+$(eval $(call BuildSubPackage,xzdiff, +xz, lzcmp lzdiff xzcmp))
+$(eval $(call BuildSubPackage,xzgrep, +xz, lzegrep lzfgrep lzgrep xzegrep xzfgrep))
+$(eval $(call BuildSubPackage,xzless, +xz, lzless))
+$(eval $(call BuildSubPackage,xzmore, +xz, lzmore))
diff --git a/package/utils/xz/patches/001-relative-pkg-config-paths.patch b/package/utils/xz/patches/001-relative-pkg-config-paths.patch
new file mode 100644
index 0000000..b89c13f
--- /dev/null
+++ b/package/utils/xz/patches/001-relative-pkg-config-paths.patch
@@ -0,0 +1,13 @@
+--- a/src/liblzma/liblzma.pc.in
++++ b/src/liblzma/liblzma.pc.in
+@@ -7,8 +7,8 @@
+ 
+ prefix=@prefix@
+ exec_prefix=@exec_prefix@
+-libdir=@libdir@
+-includedir=@includedir@
++libdir=${exec_prefix}/lib
++includedir=${prefix}/include
+ 
+ Name: liblzma
+ Description: General purpose data compression library
diff --git a/package/utils/yafut/Makefile b/package/utils/yafut/Makefile
new file mode 100644
index 0000000..e3f240f
--- /dev/null
+++ b/package/utils/yafut/Makefile
@@ -0,0 +1,37 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=yafut
+PKG_RELEASE:=1
+
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_URL=https://github.com/kempniu/yafut.git
+PKG_MIRROR_HASH:=7540e977104d41b3aca27b58fda8cd84ebec80cfe01d955712fb8dc717aff6a6
+PKG_SOURCE_DATE:=2024-06-10
+PKG_SOURCE_VERSION:=38439f8a53d33b14744bc8f938662670b9d3e361
+
+PKG_LICENSE:=GPL-2.0
+PKG_LICENSE_FILES:=LICENSE
+PKG_FLAGS:=nonshared
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/cmake.mk
+
+CMAKE_INSTALL:=1
+
+define Package/yafut
+  SECTION:=utils
+  CATEGORY:=Utilities
+  TITLE:=Yet Another File UTility
+  DEPENDS:=@NAND_SUPPORT
+endef
+
+define Package/yafut/description
+  A program for copying files from/to Yaffs file systems from userspace.
+endef
+
+define Package/yafut/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/yafut $(1)/usr/bin
+endef
+
+$(eval $(call BuildPackage,yafut))