1318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner/* Copyright (C) 2009 The Android Open Source Project 2318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner** 3318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner** This software is licensed under the terms of the GNU General Public 4318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner** License version 2, as published by the Free Software Foundation, and 5318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner** may be copied, distributed, and modified under those terms. 6318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner** 7318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner** This program is distributed in the hope that it will be useful, 8318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner** but WITHOUT ANY WARRANTY; without even the implied warranty of 9318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner** GNU General Public License for more details. 11318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner*/ 12318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner 13318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner#include "android/boot-properties.h" 14318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner#include "android/utils/debug.h" 15318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner#include "android/utils/system.h" 16318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner#include "android/hw-qemud.h" 17318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner#include "android/globals.h" 18318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner 1945041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije#include "hw/hw.h" 2045041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije 21318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner#define D(...) VERBOSE_PRINT(init,__VA_ARGS__) 22318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner 23318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner/* define T_ACTIVE to 1 to debug transport communications */ 24318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner#define T_ACTIVE 0 25318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner 26318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner#if T_ACTIVE 27318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner#define T(...) VERBOSE_PRINT(init,__VA_ARGS__) 28318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner#else 29318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner#define T(...) ((void)0) 30318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner#endif 31318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner 32d68b48725d720a06b24932b170f528929856f3dbDavid 'Digit' Turner/* this code supports the list of system properties that will 33d68b48725d720a06b24932b170f528929856f3dbDavid 'Digit' Turner * be set on boot in the emulated system. 34d68b48725d720a06b24932b170f528929856f3dbDavid 'Digit' Turner */ 35d68b48725d720a06b24932b170f528929856f3dbDavid 'Digit' Turner 36318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turnertypedef struct BootProperty { 37318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner struct BootProperty* next; 38318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner char* property; 39318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner int length; 40318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner} BootProperty; 41318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner 42318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turnerstatic BootProperty* 43318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turnerboot_property_alloc( const char* name, int namelen, 44318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner const char* value, int valuelen ) 45318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner{ 46318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner int length = namelen + 1 + valuelen; 47318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner BootProperty* prop = android_alloc( sizeof(*prop) + length + 1 ); 48318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner char* p; 49318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner 50318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner prop->next = NULL; 51318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner prop->property = p = (char*)(prop + 1); 52318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner prop->length = length; 53318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner 54318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner memcpy( p, name, namelen ); 55318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner p += namelen; 56318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner *p++ = '='; 57318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner memcpy( p, value, valuelen ); 58318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner p += valuelen; 59318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner *p = '\0'; 60318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner 61318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner return prop; 62318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner} 63318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner 6445041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thijestatic BootProperty* _boot_properties = NULL; 6545041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije/* address to store pointer to next new list element */ 66318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turnerstatic BootProperty** _boot_properties_tail = &_boot_properties; 67318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turnerstatic int _inited; 68318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner 6945041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije/* Clears all existing boot properties 7045041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije */ 7145041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thijestatic void 7245041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thijeboot_property_clear_all() 7345041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije{ 7445041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije /* free all elements of the linked list */ 7545041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije BootProperty *p = _boot_properties; 7645041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije BootProperty *next = NULL; 7745041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije while (p) { 7845041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije next = p->next; 7945041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije AFREE(p); 8045041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije p = next; 8145041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije } 8245041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije 8345041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije /* reset list administration to initial state */ 8445041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije _boot_properties = NULL; 8545041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije _boot_properties_tail = &_boot_properties; 8645041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije} 8745041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije 8845041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije/* Appends a new boot property to the end of the internal list. 8945041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije */ 90318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turnerint 91318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turnerboot_property_add2( const char* name, int namelen, 92318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner const char* value, int valuelen ) 93318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner{ 94318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner BootProperty* prop; 95318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner 96318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner /* check the lengths 97318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner */ 98318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner if (namelen > PROPERTY_MAX_NAME) 99318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner return -1; 100318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner 101318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner if (valuelen > PROPERTY_MAX_VALUE) 102318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner return -2; 103318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner 104318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner /* check that there are not invalid characters in the 105318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner * property name 106318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner */ 107318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner const char* reject = " =$*?'\""; 108318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner int nn; 109318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner 110318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner for (nn = 0; nn < namelen; nn++) { 111318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner if (strchr(reject, name[nn]) != NULL) 112318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner return -3; 113318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner } 114318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner 115318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner /* init service if needed */ 116318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner if (!_inited) { 117318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner boot_property_init_service(); 118318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner _inited = 1; 119318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner } 120318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner 121318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner D("Adding boot property: '%.*s' = '%.*s'", 122318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner namelen, name, valuelen, value); 123318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner 12445041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije /* add to the end of the internal list */ 125318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner prop = boot_property_alloc(name, namelen, value, valuelen); 126318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner 127318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner *_boot_properties_tail = prop; 128318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner _boot_properties_tail = &prop->next; 129318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner 130318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner return 0; 131318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner} 132318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner 13345041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije/* Prints the warning string corresponding to the error code returned by 13445041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije * boot_propery_add2(). 13545041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije */ 13645041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thijestatic void 13745041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thijeboot_property_raise_warning( int ret, const char* name, int namelen, 13845041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije const char* value, int valuelen ) 13945041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije{ 14045041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije switch (ret) { 14145041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije case -1: 14245041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije dwarning("boot property name too long: '%.*s'", 14345041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije namelen, name); 14445041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije break; 14545041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije case -2: 14645041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije dwarning("boot property value too long: '%.*s'", 14745041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije valuelen, value); 14845041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije break; 14945041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije case -3: 15045041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije dwarning("boot property name contains invalid chars: %.*s", 15145041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije namelen, name); 15245041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije break; 15345041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije } 15445041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije} 155318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner 156318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turnerint 157318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turnerboot_property_add( const char* name, const char* value ) 158318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner{ 159318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner int namelen = strlen(name); 160318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner int valuelen = strlen(value); 161318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner 162318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner return boot_property_add2(name, namelen, value, valuelen); 163318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner} 164318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner 16545041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije/* Saves a single BootProperty to file. 16645041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije */ 16745041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thijestatic int 16845041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thijeboot_property_save_property( QEMUFile *f, BootProperty *p ) 16945041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije{ 17045041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije /* split in key and value, so we can re-use boot_property_add (and its 17145041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije * sanity checks) when loading 17245041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije */ 173318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner 17445041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije char *split = strchr(p->property, '='); 17545041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije if (split == NULL) { 17645041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije D("%s: save failed: illegal key/value pair \"%s\" (missing '=')\n", 17745041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije __FUNCTION__, p->property); 17845041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije qemu_file_set_error(f); 17945041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije return -1; 18045041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije } 18145041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije 18245041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije *split = '\0'; /* p->property is now "<key>\0<value>\0" */ 18345041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije 18445041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije uint32_t key_buf_len = (split - p->property) + 1; // +1: '\0' terminator 18545041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije qemu_put_be32(f, key_buf_len); 18645041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije qemu_put_buffer(f, (uint8_t*) p->property, key_buf_len); 18745041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije 18845041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije uint32_t value_buf_len = p->length - key_buf_len + 1; // +1: '\0' terminator 18945041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije qemu_put_be32(f, value_buf_len); 19045041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije qemu_put_buffer(f, (uint8_t*) split + 1, value_buf_len); 19145041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije 19245041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije *split = '='; /* restore property to "<key>=<value>\0" */ 19345041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije 19445041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije return 0; 19545041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije} 19645041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije 19745041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije/* Loads a single boot property from a snapshot file 19845041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije */ 19945041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thijestatic int 20045041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thijeboot_property_load_property( QEMUFile *f ) 20145041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije{ 20245041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije int ret; 20345041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije 20445041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije /* load key */ 20545041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije uint32_t key_buf_len = qemu_get_be32(f); 20645041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije char* key = android_alloc(key_buf_len); 20745041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije if ((ret = qemu_get_buffer(f, (uint8_t*)key, key_buf_len) != key_buf_len)) { 20845041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije D("%s: key load failed: expected %d bytes, got %d\n", 20945041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije __FUNCTION__, key_buf_len, ret); 21045041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije goto fail_key; 21145041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije } 21245041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije 21345041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije /* load value */ 21445041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije uint32_t value_buf_len = qemu_get_be32(f); 21545041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije char* value = android_alloc(value_buf_len); 21645041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije if ((ret = qemu_get_buffer(f, (uint8_t*)value, value_buf_len) != value_buf_len)) { 21745041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije D("%s: value load failed: expected %d bytes, got %d\n", 21845041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije __FUNCTION__, value_buf_len, ret); 21945041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije goto fail_value; 22045041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije } 22145041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije 22245041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije /* add the property */ 22345041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije ret = boot_property_add2(key, key_buf_len - 1, value, value_buf_len - 1); 22445041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije if (ret < 0) { 22545041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije D("%s: load failed: cannot add boot property (details follow)\n", 22645041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije __FUNCTION__); 22745041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije boot_property_raise_warning(ret, key, key_buf_len - 1, value, value_buf_len - 1); 22845041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije goto fail_value; 22945041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije } 23045041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije 23145041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije return 0; 23245041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije 23345041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije /* in case of errors, clean up before return */ 23445041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije fail_value: 23545041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije AFREE(value); 23645041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije fail_key: 23745041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije AFREE(key); 23845041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije return -EIO; 23945041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije} 24045041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije 24145041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije/* Saves the number of available boot properties to file 24245041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije */ 24345041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thijestatic void 24445041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thijeboot_property_save_count( QEMUFile* f, BootProperty* p ) 24545041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije{ 24645041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije uint32_t property_count = 0; 24745041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije for (; p; p = p->next) { 24845041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije property_count++; 24945041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije } 25045041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije 25145041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije qemu_put_be32(f, property_count); 25245041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije} 25345041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije 25445041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije/* Saves all available boot properties to snapshot. 25545041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije */ 25645041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thijestatic void 25745041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thijeboot_property_save( QEMUFile* f, QemudService* service, void* opaque ) 25845041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije{ 25945041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije boot_property_save_count(f, _boot_properties); 26045041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije 26145041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije BootProperty *p = _boot_properties; 26245041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije for ( ; p; p = p->next) { 26345041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije if (boot_property_save_property(f, p)) { 26445041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije break; /* abort on error */ 26545041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije } 26645041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije } 26745041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije} 26845041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije 26945041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije/* Replaces the currently available boot properties by those stored 27045041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije * in a snapshot. 27145041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije */ 27245041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thijestatic int 27345041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thijeboot_property_load( QEMUFile* f, QemudService* service, void* opaque ) 27445041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije{ 27545041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije int ret; 27645041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije 27745041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije /* remove properties from old run */ 27845041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije boot_property_clear_all(); 27945041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije 28045041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije /* load properties from snapshot */ 28145041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije uint32_t i, property_count = qemu_get_be32(f); 28245041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije for (i = 0; i < property_count; i++) { 28345041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije if ((ret = boot_property_load_property(f))) { 28445041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije return ret; 28545041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije } 28645041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije } 28745041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije 28845041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije return 0; 28945041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije} 290318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner 291318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner#define SERVICE_NAME "boot-properties" 292318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner 293318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turnerstatic void 294318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turnerboot_property_client_recv( void* opaque, 295318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner uint8_t* msg, 296318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner int msglen, 297318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner QemudClient* client ) 298318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner{ 299318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner /* the 'list' command shall send all boot properties 300318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner * to the client, then close the connection. 301318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner */ 302318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner if (msglen == 4 && !memcmp(msg, "list", 4)) { 303318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner BootProperty* prop; 304318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner for (prop = _boot_properties; prop != NULL; prop = prop->next) { 305318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner qemud_client_send(client, (uint8_t*)prop->property, prop->length); 306318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner } 30738f8467357f731c4ced8548c6bb65e95745c7effDries Harnie 30838f8467357f731c4ced8548c6bb65e95745c7effDries Harnie /* Send a NUL to signal the end of the list. */ 30938f8467357f731c4ced8548c6bb65e95745c7effDries Harnie qemud_client_send(client, (uint8_t*)"", 1); 31038f8467357f731c4ced8548c6bb65e95745c7effDries Harnie 311318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner return; 312318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner } 313318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner 314318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner /* unknown command ? */ 315318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner D("%s: ignoring unknown command: %.*s", __FUNCTION__, msglen, msg); 316318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner} 317318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner 318318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turnerstatic QemudClient* 319318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turnerboot_property_service_connect( void* opaque, 320318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner QemudService* serv, 3214c414820910ba8553cab7ff30188575f972a9896Vladimir Chtchetkine int channel, 3224c414820910ba8553cab7ff30188575f972a9896Vladimir Chtchetkine const char* client_param ) 323318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner{ 324318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner QemudClient* client; 325318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner 3264c414820910ba8553cab7ff30188575f972a9896Vladimir Chtchetkine client = qemud_client_new( serv, channel, client_param, NULL, 327318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner boot_property_client_recv, 328871da2aa80687142bec00ef7c1112253c76c32bbOt ten Thije NULL, NULL, NULL ); 329318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner 330318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner qemud_client_set_framing(client, 1); 331318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner return client; 332318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner} 333318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner 334318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner 335318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turnervoid 336318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turnerboot_property_init_service( void ) 337318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner{ 338318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner if (!_inited) { 339318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner QemudService* serv = qemud_service_register( SERVICE_NAME, 34045041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije 1, NULL, 34145041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije boot_property_service_connect, 34245041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije boot_property_save, 34345041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije boot_property_load); 344318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner if (serv == NULL) { 345318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner derror("could not register '%s' service", SERVICE_NAME); 346318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner return; 347318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner } 348318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner D("registered '%s' qemud service", SERVICE_NAME); 349318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner } 350318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner} 351318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner 352318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner 353318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner 354318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turnervoid 355318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turnerboot_property_parse_option( const char* param ) 356318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner{ 357318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner char* q = strchr(param,'='); 358318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner const char* name; 359318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner const char* value; 360318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner int namelen, valuelen, ret; 361318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner 362318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner if (q == NULL) { 363318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner dwarning("boot property missing (=) separator: %s", param); 364318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner return; 365318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner } 366318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner 367318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner name = param; 368318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner namelen = q - param; 369318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner 370318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner value = q+1; 371318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner valuelen = strlen(name) - (namelen+1); 372318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner 373318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner ret = boot_property_add2(name, namelen, value, valuelen); 374318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner if (ret < 0) { 37545041e34b979d2ae49b985a1cb98117e71904a16Ot ten Thije boot_property_raise_warning(ret, name, namelen, value, valuelen); 376318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner } 377318e4f294c181df33cf2541763904565b29bcccbDavid 'Digit' Turner} 378