aboutsummaryrefslogtreecommitdiffstats
path: root/android/boot-properties.c
diff options
context:
space:
mode:
authorDavid 'Digit' Turner <digit@google.com>2009-05-25 18:01:03 +0200
committerDavid 'Digit' Turner <digit@google.com>2009-05-26 17:23:25 +0200
commit318e4f294c181df33cf2541763904565b29bcccb (patch)
tree35b5085c9e35e91967e2d4a4db80e28ec086e1d3 /android/boot-properties.c
parent0d47fe5756b1f243e8d65968cd73c0119363f909 (diff)
downloadexternal_qemu-318e4f294c181df33cf2541763904565b29bcccb.zip
external_qemu-318e4f294c181df33cf2541763904565b29bcccb.tar.gz
external_qemu-318e4f294c181df33cf2541763904565b29bcccb.tar.bz2
This adds the '-prop <name>=<value>' option which is used to set
boot-time system properties from the command line. This is done by implementing a new 'boot-properties' qemud service in the emulator. This is to be used by the 'qemu-props' helper program that will be invoked by /system/etc/init.goldfish.rc to read a list of system properties from the emulator and set them in the emulated system during boot.
Diffstat (limited to 'android/boot-properties.c')
-rw-r--r--android/boot-properties.c214
1 files changed, 214 insertions, 0 deletions
diff --git a/android/boot-properties.c b/android/boot-properties.c
new file mode 100644
index 0000000..1c714e9
--- /dev/null
+++ b/android/boot-properties.c
@@ -0,0 +1,214 @@
+/* Copyright (C) 2009 The Android Open Source Project
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** 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.
+*/
+
+#include "android/boot-properties.h"
+#include "android/utils/debug.h"
+#include "android/utils/system.h"
+#include "android/hw-qemud.h"
+#include "android/globals.h"
+
+#define D(...) VERBOSE_PRINT(init,__VA_ARGS__)
+
+/* define T_ACTIVE to 1 to debug transport communications */
+#define T_ACTIVE 0
+
+#if T_ACTIVE
+#define T(...) VERBOSE_PRINT(init,__VA_ARGS__)
+#else
+#define T(...) ((void)0)
+#endif
+
+typedef struct BootProperty {
+ struct BootProperty* next;
+ char* property;
+ int length;
+} BootProperty;
+
+static BootProperty*
+boot_property_alloc( const char* name, int namelen,
+ const char* value, int valuelen )
+{
+ int length = namelen + 1 + valuelen;
+ BootProperty* prop = android_alloc( sizeof(*prop) + length + 1 );
+ char* p;
+
+ prop->next = NULL;
+ prop->property = p = (char*)(prop + 1);
+ prop->length = length;
+
+ memcpy( p, name, namelen );
+ p += namelen;
+ *p++ = '=';
+ memcpy( p, value, valuelen );
+ p += valuelen;
+ *p = '\0';
+
+ return prop;
+}
+
+static BootProperty* _boot_properties;
+static BootProperty** _boot_properties_tail = &_boot_properties;
+static int _inited;
+
+/* this code supports the list of system properties that will
+ * be set on boot in the emulated system.
+ */
+
+int
+boot_property_add2( const char* name, int namelen,
+ const char* value, int valuelen )
+{
+ BootProperty* prop;
+
+ /* check the lengths
+ */
+ if (namelen > PROPERTY_MAX_NAME)
+ return -1;
+
+ if (valuelen > PROPERTY_MAX_VALUE)
+ return -2;
+
+ /* check that there are not invalid characters in the
+ * property name
+ */
+ const char* reject = " =$*?'\"";
+ int nn;
+
+ for (nn = 0; nn < namelen; nn++) {
+ if (strchr(reject, name[nn]) != NULL)
+ return -3;
+ }
+
+ /* init service if needed */
+ if (!_inited) {
+ boot_property_init_service();
+ _inited = 1;
+ }
+
+ D("Adding boot property: '%.*s' = '%.*s'",
+ namelen, name, valuelen, value);
+
+ /* add to the internal list */
+ prop = boot_property_alloc(name, namelen, value, valuelen);
+
+ *_boot_properties_tail = prop;
+ _boot_properties_tail = &prop->next;
+
+ return 0;
+}
+
+
+int
+boot_property_add( const char* name, const char* value )
+{
+ int namelen = strlen(name);
+ int valuelen = strlen(value);
+
+ return boot_property_add2(name, namelen, value, valuelen);
+}
+
+
+
+#define SERVICE_NAME "boot-properties"
+
+static void
+boot_property_client_recv( void* opaque,
+ uint8_t* msg,
+ int msglen,
+ QemudClient* client )
+{
+ /* the 'list' command shall send all boot properties
+ * to the client, then close the connection.
+ */
+ if (msglen == 4 && !memcmp(msg, "list", 4)) {
+ BootProperty* prop;
+ for (prop = _boot_properties; prop != NULL; prop = prop->next) {
+ qemud_client_send(client, (uint8_t*)prop->property, prop->length);
+ }
+ qemud_client_close(client);
+ return;
+ }
+
+ /* unknown command ? */
+ D("%s: ignoring unknown command: %.*s", __FUNCTION__, msglen, msg);
+}
+
+static QemudClient*
+boot_property_service_connect( void* opaque,
+ QemudService* serv,
+ int channel )
+{
+ QemudClient* client;
+
+ client = qemud_client_new( serv, channel, NULL,
+ boot_property_client_recv,
+ NULL );
+
+ qemud_client_set_framing(client, 1);
+ return client;
+}
+
+
+void
+boot_property_init_service( void )
+{
+ if (!_inited) {
+ QemudService* serv = qemud_service_register( SERVICE_NAME,
+ 1, NULL,
+ boot_property_service_connect );
+ if (serv == NULL) {
+ derror("could not register '%s' service", SERVICE_NAME);
+ return;
+ }
+ D("registered '%s' qemud service", SERVICE_NAME);
+ }
+}
+
+
+
+void
+boot_property_parse_option( const char* param )
+{
+ char* q = strchr(param,'=');
+ const char* name;
+ const char* value;
+ int namelen, valuelen, ret;
+
+ if (q == NULL) {
+ dwarning("boot property missing (=) separator: %s", param);
+ return;
+ }
+
+ name = param;
+ namelen = q - param;
+
+ value = q+1;
+ valuelen = strlen(name) - (namelen+1);
+
+ ret = boot_property_add2(name, namelen, value, valuelen);
+ if (ret < 0) {
+ switch (ret) {
+ case -1:
+ dwarning("boot property name too long: '%.*s'",
+ namelen, name);
+ break;
+ case -2:
+ dwarning("boot property value too long: '%.*s'",
+ valuelen, value);
+ break;
+ case -3:
+ dwarning("boot property name contains invalid chars: %.*s",
+ namelen, name);
+ break;
+ }
+ }
+}