Merge commit 'goog/master' into merge_master

This commit is contained in:
Mathias Agopian 2009-06-19 17:41:17 -07:00
commit fda03b7562
15 changed files with 317 additions and 41 deletions

View File

@ -126,6 +126,9 @@ static struct perms_ devperms[] = {
{ "/dev/msm_mp3", 0660, AID_SYSTEM, AID_AUDIO, 1 },
{ "/dev/msm_audpre", 0660, AID_SYSTEM, AID_AUDIO, 0 },
{ "/dev/htc-acoustic", 0660, AID_SYSTEM, AID_AUDIO, 0 },
{ "/dev/snd/dsp", 0660, AID_SYSTEM, AID_AUDIO, 0 },
{ "/dev/snd/dsp1", 0660, AID_SYSTEM, AID_AUDIO, 0 },
{ "/dev/snd/mixer", 0660, AID_SYSTEM, AID_AUDIO, 0 },
{ "/dev/smd0", 0640, AID_RADIO, AID_RADIO, 0 },
{ "/dev/qemu_trace", 0666, AID_SYSTEM, AID_SYSTEM, 0 },
{ "/dev/qmi", 0640, AID_RADIO, AID_RADIO, 0 },

View File

@ -46,8 +46,11 @@
#define LOG_API(...) do {} while(0)
// #define LOG_API(...) fprintf (stderr, __VA_ARGS__)
// #define ENABLE_ARM_DISASSEMBLY
#define LOG_STACK(...) do {} while(0)
// #define LOG_STACK(...) fprintf (stderr, __VA_ARGS__)
// #define ENABLE_ARM_DISASSEMBLY
// #define PROVIDE_TRACE_CODEGEN
namespace acc {
@ -399,27 +402,38 @@ class Compiler : public ErrorSink {
class ARMCodeGenerator : public CodeGenerator {
public:
ARMCodeGenerator() {}
virtual ~ARMCodeGenerator() {}
/* returns address to patch with local variable size
*/
virtual int functionEntry(int argCount) {
LOG_API("functionEntry(%d);\n", argCount);
mStackUse = 0;
// sp -> arg4 arg5 ...
// Push our register-based arguments back on the stack
if (argCount > 0) {
int regArgCount = argCount <= 4 ? argCount : 4;
o4(0xE92D0000 | ((1 << argCount) - 1)); // stmfd sp!, {}
mStackUse += regArgCount * 4;
}
// sp -> arg0 arg1 ...
o4(0xE92D4800); // stmfd sp!, {fp, lr}
mStackUse += 2 * 4;
// sp, fp -> oldfp, retadr, arg0 arg1 ....
o4(0xE1A0B00D); // mov fp, sp
LOG_STACK("functionEntry: %d\n", mStackUse);
return o4(0xE24DD000); // sub sp, sp, # <local variables>
// We don't know how many local variables we are going to use,
// but we will round the allocation up to a multiple of
// STACK_ALIGNMENT, so it won't affect the stack alignment.
}
virtual void functionExit(int argCount, int localVariableAddress, int localVariableSize) {
LOG_API("functionExit(%d, %d, %d);\n", argCount, localVariableAddress, localVariableSize);
// Round local variable size up to a multiple of stack alignment
localVariableSize = ((localVariableSize + STACK_ALIGNMENT - 1) /
STACK_ALIGNMENT) * STACK_ALIGNMENT;
// Patch local variable allocation code:
if (localVariableSize < 0 || localVariableSize > 255) {
error("localVariables out of range: %d", localVariableSize);
@ -547,11 +561,6 @@ class Compiler : public ErrorSink {
error("Unimplemented op %d\n", op);
break;
}
#if 0
o(decodeOp(op));
if (op == OP_MOD)
o(0x92); /* xchg %edx, %eax */
#endif
}
virtual void clearR1() {
@ -562,11 +571,15 @@ class Compiler : public ErrorSink {
virtual void pushR0() {
LOG_API("pushR0();\n");
o4(0xE92D0001); // stmfd sp!,{r0}
mStackUse += 4;
LOG_STACK("pushR0: %d\n", mStackUse);
}
virtual void popR1() {
LOG_API("popR1();\n");
o4(0xE8BD0002); // ldmfd sp!,{r1}
mStackUse -= 4;
LOG_STACK("popR1: %d\n", mStackUse);
}
virtual void storeR0ToR1(bool isInt) {
@ -690,15 +703,31 @@ class Compiler : public ErrorSink {
virtual void endFunctionCallArguments(int a, int l) {
LOG_API("endFunctionCallArguments(0x%08x, %d);\n", a, l);
int argCount = l >> 2;
int argumentStackUse = l;
if (argCount > 0) {
int regArgCount = argCount > 4 ? 4 : argCount;
argumentStackUse -= regArgCount * 4;
o4(0xE8BD0000 | ((1 << regArgCount) - 1)); // ldmfd sp!,{}
}
mStackUse += argumentStackUse;
// Align stack.
int missalignment = mStackUse - ((mStackUse / STACK_ALIGNMENT)
* STACK_ALIGNMENT);
mStackAlignmentAdjustment = 0;
if (missalignment > 0) {
mStackAlignmentAdjustment = STACK_ALIGNMENT - missalignment;
}
l += mStackAlignmentAdjustment;
if (l < 0 || l > 0x3FC) {
error("L out of range for stack adjustment: 0x%08x", l);
}
* (int*) a = 0xE24DDF00 | (l >> 2); // sub sp, sp, #0 << 2
int argCount = l >> 2;
if (argCount > 0) {
int regArgCount = argCount > 4 ? 4 : argCount;
o4(0xE8BD0000 | ((1 << regArgCount) - 1)); // ldmfd sp!,{}
}
mStackUse += mStackAlignmentAdjustment;
LOG_STACK("endFunctionCallArguments mStackUse: %d, mStackAlignmentAdjustment %d\n",
mStackUse, mStackAlignmentAdjustment);
}
virtual int callForward(int symbol) {
@ -727,7 +756,7 @@ class Compiler : public ErrorSink {
LOG_API("callIndirect(%d);\n", l);
int argCount = l >> 2;
int poppedArgs = argCount > 4 ? 4 : argCount;
int adjustedL = l - (poppedArgs << 2);
int adjustedL = l - (poppedArgs << 2) + mStackAlignmentAdjustment;
if (adjustedL < 0 || adjustedL > 4096-4) {
error("l out of range for stack offset: 0x%08x", l);
}
@ -739,12 +768,15 @@ class Compiler : public ErrorSink {
LOG_API("adjustStackAfterCall(%d, %d);\n", l, isIndirect);
int argCount = l >> 2;
int stackArgs = argCount > 4 ? argCount - 4 : 0;
int stackUse = stackArgs + (isIndirect ? 1 : 0);
int stackUse = stackArgs + (isIndirect ? 1 : 0)
+ (mStackAlignmentAdjustment >> 2);
if (stackUse) {
if (stackUse < 0 || stackUse > 255) {
error("L out of range for stack adjustment: 0x%08x", l);
}
o4(0xE28DDF00 | stackUse); // add sp, sp, #stackUse << 2
mStackUse -= stackUse * 4;
LOG_STACK("adjustStackAfterCall: %d\n", mStackUse);
}
}
@ -858,6 +890,13 @@ class Compiler : public ErrorSink {
static int runtime_MOD(int a, int b) {
return b % a;
}
static const int STACK_ALIGNMENT = 8;
int mStackUse;
// This variable holds the amount we adjusted the stack in the most
// recent endFunctionCallArguments call. It's examined by the
// following adjustStackAfterCall call.
int mStackAlignmentAdjustment;
};
#endif // PROVIDE_ARM_CODEGEN
@ -981,7 +1020,9 @@ class Compiler : public ErrorSink {
if (isIndirect) {
l += 4;
}
oad(0xc481, l); /* add $xxx, %esp */
if (l > 0) {
oad(0xc481, l); /* add $xxx, %esp */
}
}
virtual int jumpOffset() {
@ -2315,8 +2356,7 @@ class Compiler : public ErrorSink {
} else {
pGen->callRelative(n - codeBuf.getPC() - pGen->jumpOffset());
}
if (l | (n == 1))
pGen->adjustStackAfterCall(l, n == 1);
pGen->adjustStackAfterCall(l, n == 1);
}
}
@ -3025,6 +3065,11 @@ void accGetPragmas(ACCscript* script, ACCsizei* actualStringCount,
script->compiler.getPragmas(actualStringCount, maxStringCount, strings);
}
extern "C"
void accDisassemble(ACCscript* script) {
script->compiler.disassemble(stderr);
}
} // namespace acc

View File

@ -29,6 +29,11 @@ int run(MainPtr mainFunc, int argc, char** argv) {
return mainFunc(argc, argv);
}
// Private API for development:
extern "C"
void accDisassemble(ACCscript* script);
int main(int argc, char** argv) {
const char* inFile = NULL;
bool printListing;
@ -109,6 +114,10 @@ int main(int argc, char** argv) {
}
}
if (printListing) {
accDisassemble(script);
}
if (runResults) {
accGetScriptLabel(script, "main", (ACCvoid**) & mainPointer);

View File

@ -13,7 +13,7 @@ enum {
// central directory entries
ENTRY_SIGNATURE = 0x02014b50,
ENTRY_LEN = 46, // CentralDirEnt len, excl. var fields
// local file header
LFH_SIZE = 30,
};
@ -73,8 +73,6 @@ read_central_directory_entry(Zipfile* file, Zipentry* entry,
unsigned short lastModFileTime;
unsigned short lastModFileDate;
unsigned long crc32;
unsigned long compressedSize;
unsigned long uncompressedSize;
unsigned short extraFieldLength;
unsigned short fileCommentLength;
unsigned short diskNumberStart;
@ -85,7 +83,7 @@ read_central_directory_entry(Zipfile* file, Zipentry* entry,
const unsigned char* fileComment;
unsigned int dataOffset;
unsigned short lfhExtraFieldSize;
p = *buf;
@ -106,7 +104,7 @@ read_central_directory_entry(Zipfile* file, Zipentry* entry,
lastModFileTime = read_le_short(&p[0x0c]);
lastModFileDate = read_le_short(&p[0x0e]);
crc32 = read_le_int(&p[0x10]);
compressedSize = read_le_int(&p[0x14]);
entry->compressedSize = read_le_int(&p[0x14]);
entry->uncompressedSize = read_le_int(&p[0x18]);
entry->fileNameLength = read_le_short(&p[0x1c]);
extraFieldLength = read_le_short(&p[0x1e]);
@ -141,14 +139,14 @@ read_central_directory_entry(Zipfile* file, Zipentry* entry,
fileComment = NULL;
}
p += fileCommentLength;
*buf = p;
// the size of the extraField in the central dir is how much data there is,
// but the one in the local file header also contains some padding.
p = file->buf + localHeaderRelOffset;
extraFieldLength = read_le_short(&p[0x1c]);
dataOffset = localHeaderRelOffset + LFH_SIZE
+ entry->fileNameLength + extraFieldLength;
entry->data = file->buf + dataOffset;
@ -243,7 +241,7 @@ read_central_dir(Zipfile *file)
free(entry);
goto bail;
}
// add it to our list
entry->next = file->entries;
file->entries = entry;
@ -253,4 +251,3 @@ read_central_dir(Zipfile *file)
bail:
return -1;
}

View File

@ -82,13 +82,13 @@ uninflate(unsigned char* out, int unlen, const unsigned char* in, int clen)
unsigned long crc;
int err = 0;
int zerr;
memset(&zstream, 0, sizeof(zstream));
zstream.zalloc = Z_NULL;
zstream.zfree = Z_NULL;
zstream.opaque = Z_NULL;
zstream.next_in = (void*)in;
zstream.avail_in = unlen;
zstream.avail_in = clen;
zstream.next_out = (Bytef*) out;
zstream.avail_out = unlen;
zstream.data_type = Z_UNKNOWN;
@ -99,7 +99,7 @@ uninflate(unsigned char* out, int unlen, const unsigned char* in, int clen)
if (zerr != Z_OK) {
return -1;
}
// uncompress the data
zerr = inflate(&zstream, Z_FINISH);
if (zerr != Z_STREAM_END) {
@ -107,7 +107,7 @@ uninflate(unsigned char* out, int unlen, const unsigned char* in, int clen)
zstream.total_out);
err = -1;
}
inflateEnd(&zstream);
return err;
}

View File

@ -94,7 +94,7 @@
2800 gtalkservice (eventType|1)
# This event is logged for GTalk connection state changes. The status field is an int, but
# it really contains 4 separate values, each taking up a byte
# (eventType, connection state, connection error, network state)
# (eventType << 24) + (connection state << 16) + (connection error << 8) + network state
2801 gtalk_connection (status|1)
2802 watchdog (Service|3)
@ -135,6 +135,26 @@
3100 boot_progress_pms_ready (time|2|3)
# + check activity_launch_time for Home app
# This event is logged when GTalk connection is closed.
# The status field is an int, but contains 2 different values, it's represented as
#
# (networkType << 8) + connection error
#
# the possible error values are
#
# no_error=0, no_network=1, connection_failed=2, unknown_host=3, auth_failed=4,
# auth_expired=5, heart_beat_timeout=6, server_error=7, server_reject_rate_limiting=8, unknown=10
#
# duration is the connection duration.
4000 gtalk_conn_close (status|1),(duration|1)
# This event is logged for GTalk heartbeat resets
# interval_and_nt contains both the heartbeat interval and the network type, It's represented as
# (networkType << 16) + interval
# interval is in seconds; network type can be 0 (mobile) or 1 (wifi); ip is the host ip addr.
4001 gtalk_heartbeat_reset (interval_and_nt|1),(ip|3)
# Do not change these names without updating the checkin_events setting in
# google3/googledata/wireless/android/provisioning/gservices.config !!
#

View File

@ -33,7 +33,8 @@ LOCAL_SRC_FILES:= \
SupplicantScanResultsEvent.cpp \
SupplicantConnectionTimeoutEvent.cpp \
SupplicantDisconnectedEvent.cpp \
SupplicantStatus.cpp
SupplicantStatus.cpp \
TiwlanEventListener.cpp
LOCAL_MODULE:= nexus

View File

@ -29,6 +29,7 @@ SupplicantAssociatingEvent::SupplicantAssociatingEvent(int level, char *event,
mBssid = NULL;
mSsid = NULL;
mFreq = -1;
// SSID 'default'
// OR

View File

@ -17,7 +17,7 @@
#include <stdlib.h>
#include <string.h>
#define LOG_TAG "SupplicantState"
#define LOG_TAG "SupplicantStatus"
#include <cutils/log.h>
#include "SupplicantStatus.h"
@ -52,18 +52,37 @@ SupplicantStatus *SupplicantStatus::createStatus(char *data, int len) {
char *next = data;
char *line;
while((line = strsep(&next, "\n"))) {
char *token = strsep(&next, "=");
char *value = strsep(&next, "=");
char *line_next = line;
char *token = strsep(&line_next, "=");
char *value = strsep(&line_next, "=");
if (!strcmp(token, "bssid"))
bssid = strdup(value);
else if (!strcmp(token, "ssid"))
ssid = strdup(value);
else if (!strcmp(token, "id"))
id = atoi(value);
else if (!strcmp(token, "wpa_state"))
state = atoi(value);
else
else if (!strcmp(token, "wpa_state")) {
if (!strcmp(value, "DISCONNECTED"))
state = SupplicantState::DISCONNECTED;
else if (!strcmp(value, "INACTIVE"))
state = SupplicantState::INACTIVE;
else if (!strcmp(value, "SCANNING"))
state = SupplicantState::SCANNING;
else if (!strcmp(value, "ASSOCIATING"))
state = SupplicantState::ASSOCIATING;
else if (!strcmp(value, "ASSOCIATED"))
state = SupplicantState::ASSOCIATED;
else if (!strcmp(value, "FOURWAY_HANDSHAKE"))
state = SupplicantState::FOURWAY_HANDSHAKE;
else if (!strcmp(value, "GROUP_HANDSHAKE"))
state = SupplicantState::GROUP_HANDSHAKE;
else if (!strcmp(value, "COMPLETED"))
state = SupplicantState::COMPLETED;
else if (!strcmp(value, "IDLE"))
state = SupplicantState::IDLE;
else
LOGE("Unknown supplicant state '%s'", value);
} else
LOGD("Ignoring unsupported status token '%s'", token);
}

View File

@ -0,0 +1,61 @@
/*
* 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 <pthread.h>
#include <sys/types.h>
#include <sys/types.h>
#include <sys/socket.h>
#define LOG_TAG "TiwlanEventListener"
#include <cutils/log.h>
#include "TiwlanEventListener.h"
TiwlanEventListener::TiwlanEventListener(int socket) :
SocketListener(socket, false) {
}
bool TiwlanEventListener::onDataAvailable(SocketClient *cli) {
struct ipc_ev_data *data;
if (!(data = (struct ipc_ev_data *) malloc(sizeof(struct ipc_ev_data)))) {
LOGE("Failed to allocate packet (out of memory)");
return true;
}
if (recv(cli->getSocket(), data, sizeof(struct ipc_ev_data), 0) < 0) {
LOGE("recv failed (%s)", strerror(errno));
goto out;
}
if (data->event_type == IPC_EVENT_LINK_SPEED) {
uint32_t *spd = (uint32_t *) data->buffer;
*spd /= 2;
// LOGD("Link speed = %u MB/s", *spd);
} else if (data->event_type == IPC_EVENT_LOW_SNR) {
LOGW("Low signal/noise ratio");
} else if (data->event_type == IPC_EVENT_LOW_RSSI) {
LOGW("Low RSSI");
} else {
// LOGD("Dropping unhandled driver event %d", data->event_type);
}
// TODO: Tell WifiController about the event
out:
free(data);
return true;
}

View File

@ -0,0 +1,55 @@
/*
* 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 _TIWLAN_EVENT_LISTENER_H__
#define _TIWLAN_EVENT_LISTENER_H__
#include <sysutils/SocketListener.h>
struct wpa_ctrl;
class SocketClient;
class ITiwlanEventHandler;
class TiwlanEventFactory;
class TiwlanEventListener: public SocketListener {
public:
TiwlanEventListener(int sock);
virtual ~TiwlanEventListener() {}
protected:
virtual bool onDataAvailable(SocketClient *c);
};
// TODO: Move all this crap into a factory
#define TI_DRIVER_MSG_PORT 9001
#define IPC_EVENT_LINK_SPEED 2
#define IPC_EVENT_LOW_SNR 13
#define IPC_EVENT_LOW_RSSI 14
struct ipc_ev_data {
uint32_t event_type;
void *event_id;
uint32_t process_id;
uint32_t delivery_type;
uint32_t user_param;
void *event_callback;
uint32_t bufferSize;
uint8_t buffer[2048];
};
#endif

View File

@ -18,6 +18,9 @@
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <cutils/properties.h>
#define LOG_TAG "TiwlanWifiController"
@ -25,6 +28,7 @@
#include "PropertyManager.h"
#include "TiwlanWifiController.h"
#include "TiwlanEventListener.h"
#define DRIVER_PROP_NAME "wlan.driver.status"
@ -36,6 +40,8 @@ TiwlanWifiController::TiwlanWifiController(PropertyManager *propmngr,
char *modargs) :
WifiController(propmngr, handlers, modpath, modname,
modargs) {
mEventListener = NULL;
mListenerSock = -1;
}
int TiwlanWifiController::powerUp() {
@ -43,6 +49,13 @@ int TiwlanWifiController::powerUp() {
}
int TiwlanWifiController::powerDown() {
if (mEventListener) {
delete mEventListener;
close(mListenerSock);
mListenerSock = -1;
mEventListener = NULL;
}
return 0; // Powerdown is currently done when the driver is unloaded
}
@ -60,17 +73,56 @@ int TiwlanWifiController::loadFirmware() {
// Wait for driver to be ready
while (count-- > 0) {
if (property_get(DRIVER_PROP_NAME, driver_status, NULL)) {
if (strcmp(driver_status, "ok") == 0)
if (!strcmp(driver_status, "ok")) {
LOGD("Firmware loaded OK");
if (startDriverEventListener()) {
LOGW("Failed to start driver event listener");
}
return 0;
else if (strcmp(DRIVER_PROP_NAME, "failed") == 0)
} else if (!strcmp(DRIVER_PROP_NAME, "failed")) {
LOGE("Firmware load failed");
return -1;
}
}
usleep(200000);
}
property_set(DRIVER_PROP_NAME, "timeout");
LOGE("Firmware load timed out");
return -1;
}
int TiwlanWifiController::startDriverEventListener() {
struct sockaddr_in addr;
int s;
if ((s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
return -1;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(TI_DRIVER_MSG_PORT);
if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
close(s);
return -1;
}
mEventListener = new TiwlanEventListener(s);
if (mEventListener->startListener()) {
LOGE("Error starting driver listener (%s)", strerror(errno));
delete mEventListener;
mEventListener = NULL;
close(s);
return -1;
}
mListenerSock = s;
return 0;
}
bool TiwlanWifiController::isFirmwareLoaded() {
// Always load the firmware
return false;

View File

@ -21,8 +21,12 @@
#include "WifiController.h"
class IControllerHandler;
class TiwlanEventListener;
class TiwlanWifiController : public WifiController {
int mListenerSock;
TiwlanEventListener *mEventListener;
public:
TiwlanWifiController(PropertyManager *propmngr, IControllerHandler *handlers, char *modpath, char *modname, char *modargs);
virtual ~TiwlanWifiController() {}
@ -32,5 +36,8 @@ public:
virtual bool isPoweredUp();
virtual int loadFirmware();
virtual bool isFirmwareLoaded();
private:
int startDriverEventListener();
};
#endif

View File

@ -69,7 +69,9 @@ int WifiController::stop() {
}
int WifiController::enable() {
if (!isPoweredUp()) {
LOGI("Powering up");
sendStatusBroadcast("Powering up WiFi hardware");
if (powerUp()) {
LOGE("Powerup failed (%s)", strerror(errno));
@ -78,6 +80,7 @@ int WifiController::enable() {
}
if (mModuleName[0] != '\0' && !isKernelModuleLoaded(mModuleName)) {
LOGI("Loading driver");
sendStatusBroadcast("Loading WiFi driver");
if (loadKernelModule(mModulePath, mModuleArgs)) {
LOGE("Kernel module load failed (%s)", strerror(errno));
@ -86,6 +89,7 @@ int WifiController::enable() {
}
if (!isFirmwareLoaded()) {
LOGI("Loading firmware");
sendStatusBroadcast("Loading WiFI firmware");
if (loadFirmware()) {
LOGE("Firmware load failed (%s)", strerror(errno));
@ -94,6 +98,7 @@ int WifiController::enable() {
}
if (!mSupplicant->isStarted()) {
LOGI("Starting WPA Supplicant");
sendStatusBroadcast("Starting WPA Supplicant");
if (mSupplicant->start()) {
LOGE("Supplicant start failed (%s)", strerror(errno));
@ -113,6 +118,7 @@ int WifiController::enable() {
mPropMngr->registerProperty("wifi.scanmode", this);
mPropMngr->registerProperty("wifi.interface", this);
LOGI("Enabled successfully");
return 0;
out_unloadmodule:

View File

@ -51,7 +51,7 @@ loglevel 3
mkdir /dev/cpuctl/bg_non_interactive
chown system system /dev/cpuctl/bg_non_interactive/tasks
chmod 0777 /dev/cpuctl/bg_non_interactive/tasks
write /dev/cpuctl/bg_non_interactive/cpu.shares 1
write /dev/cpuctl/bg_non_interactive/cpu.shares 16
# mount mtd partitions
# Mount /system rw first to give the filesystem a chance to save a checkpoint