diff options
author | Ot ten Thije <ottenthije@google.com> | 2010-10-21 09:55:03 -0700 |
---|---|---|
committer | Android Code Review <code-review@android.com> | 2010-10-21 09:55:03 -0700 |
commit | 6133adcd101e17118354e64771c52355dbafb1d7 (patch) | |
tree | a1e891e49d44c3ec3998d108b6cb53d350f26aa4 /android | |
parent | 9690461f3f0a7710d8f1b364563395e2baadb085 (diff) | |
parent | 45041e34b979d2ae49b985a1cb98117e71904a16 (diff) | |
download | external_qemu-6133adcd101e17118354e64771c52355dbafb1d7.zip external_qemu-6133adcd101e17118354e64771c52355dbafb1d7.tar.gz external_qemu-6133adcd101e17118354e64771c52355dbafb1d7.tar.bz2 |
Merge "Added state snapshot support for QemuD service "boot properties"."
Diffstat (limited to 'android')
-rw-r--r-- | android/boot-properties.c | 196 |
1 files changed, 177 insertions, 19 deletions
diff --git a/android/boot-properties.c b/android/boot-properties.c index c094202..1a86010 100644 --- a/android/boot-properties.c +++ b/android/boot-properties.c @@ -16,6 +16,8 @@ #include "android/hw-qemud.h" #include "android/globals.h" +#include "hw/hw.h" + #define D(...) VERBOSE_PRINT(init,__VA_ARGS__) /* define T_ACTIVE to 1 to debug transport communications */ @@ -59,10 +61,32 @@ boot_property_alloc( const char* name, int namelen, return prop; } -static BootProperty* _boot_properties; +static BootProperty* _boot_properties = NULL; +/* address to store pointer to next new list element */ static BootProperty** _boot_properties_tail = &_boot_properties; static int _inited; +/* Clears all existing boot properties + */ +static void +boot_property_clear_all() +{ + /* free all elements of the linked list */ + BootProperty *p = _boot_properties; + BootProperty *next = NULL; + while (p) { + next = p->next; + AFREE(p); + p = next; + } + + /* reset list administration to initial state */ + _boot_properties = NULL; + _boot_properties_tail = &_boot_properties; +} + +/* Appends a new boot property to the end of the internal list. + */ int boot_property_add2( const char* name, int namelen, const char* value, int valuelen ) @@ -97,7 +121,7 @@ boot_property_add2( const char* name, int namelen, D("Adding boot property: '%.*s' = '%.*s'", namelen, name, valuelen, value); - /* add to the internal list */ + /* add to the end of the internal list */ prop = boot_property_alloc(name, namelen, value, valuelen); *_boot_properties_tail = prop; @@ -106,6 +130,28 @@ boot_property_add2( const char* name, int namelen, return 0; } +/* Prints the warning string corresponding to the error code returned by + * boot_propery_add2(). + */ +static void +boot_property_raise_warning( int ret, const char* name, int namelen, + const char* value, int valuelen ) +{ + 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; + } +} int boot_property_add( const char* name, const char* value ) @@ -116,7 +162,131 @@ boot_property_add( const char* name, const char* value ) return boot_property_add2(name, namelen, value, valuelen); } +/* Saves a single BootProperty to file. + */ +static int +boot_property_save_property( QEMUFile *f, BootProperty *p ) +{ + /* split in key and value, so we can re-use boot_property_add (and its + * sanity checks) when loading + */ + char *split = strchr(p->property, '='); + if (split == NULL) { + D("%s: save failed: illegal key/value pair \"%s\" (missing '=')\n", + __FUNCTION__, p->property); + qemu_file_set_error(f); + return -1; + } + + *split = '\0'; /* p->property is now "<key>\0<value>\0" */ + + uint32_t key_buf_len = (split - p->property) + 1; // +1: '\0' terminator + qemu_put_be32(f, key_buf_len); + qemu_put_buffer(f, (uint8_t*) p->property, key_buf_len); + + uint32_t value_buf_len = p->length - key_buf_len + 1; // +1: '\0' terminator + qemu_put_be32(f, value_buf_len); + qemu_put_buffer(f, (uint8_t*) split + 1, value_buf_len); + + *split = '='; /* restore property to "<key>=<value>\0" */ + + return 0; +} + +/* Loads a single boot property from a snapshot file + */ +static int +boot_property_load_property( QEMUFile *f ) +{ + int ret; + + /* load key */ + uint32_t key_buf_len = qemu_get_be32(f); + char* key = android_alloc(key_buf_len); + if ((ret = qemu_get_buffer(f, (uint8_t*)key, key_buf_len) != key_buf_len)) { + D("%s: key load failed: expected %d bytes, got %d\n", + __FUNCTION__, key_buf_len, ret); + goto fail_key; + } + + /* load value */ + uint32_t value_buf_len = qemu_get_be32(f); + char* value = android_alloc(value_buf_len); + if ((ret = qemu_get_buffer(f, (uint8_t*)value, value_buf_len) != value_buf_len)) { + D("%s: value load failed: expected %d bytes, got %d\n", + __FUNCTION__, value_buf_len, ret); + goto fail_value; + } + + /* add the property */ + ret = boot_property_add2(key, key_buf_len - 1, value, value_buf_len - 1); + if (ret < 0) { + D("%s: load failed: cannot add boot property (details follow)\n", + __FUNCTION__); + boot_property_raise_warning(ret, key, key_buf_len - 1, value, value_buf_len - 1); + goto fail_value; + } + + return 0; + + /* in case of errors, clean up before return */ + fail_value: + AFREE(value); + fail_key: + AFREE(key); + return -EIO; +} + +/* Saves the number of available boot properties to file + */ +static void +boot_property_save_count( QEMUFile* f, BootProperty* p ) +{ + uint32_t property_count = 0; + for (; p; p = p->next) { + property_count++; + } + + qemu_put_be32(f, property_count); +} + +/* Saves all available boot properties to snapshot. + */ +static void +boot_property_save( QEMUFile* f, QemudService* service, void* opaque ) +{ + boot_property_save_count(f, _boot_properties); + + BootProperty *p = _boot_properties; + for ( ; p; p = p->next) { + if (boot_property_save_property(f, p)) { + break; /* abort on error */ + } + } +} + +/* Replaces the currently available boot properties by those stored + * in a snapshot. + */ +static int +boot_property_load( QEMUFile* f, QemudService* service, void* opaque ) +{ + int ret; + + /* remove properties from old run */ + boot_property_clear_all(); + + /* load properties from snapshot */ + uint32_t i, property_count = qemu_get_be32(f); + for (i = 0; i < property_count; i++) { + if ((ret = boot_property_load_property(f))) { + return ret; + } + } + + return 0; +} #define SERVICE_NAME "boot-properties" @@ -167,9 +337,10 @@ boot_property_init_service( void ) { if (!_inited) { QemudService* serv = qemud_service_register( SERVICE_NAME, - 1, NULL, - boot_property_service_connect, - NULL, NULL); + 1, NULL, + boot_property_service_connect, + boot_property_save, + boot_property_load); if (serv == NULL) { derror("could not register '%s' service", SERVICE_NAME); return; @@ -201,19 +372,6 @@ boot_property_parse_option( const char* param ) 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; - } + boot_property_raise_warning(ret, name, namelen, value, valuelen); } } |