.put = put_uint64,
};
+/* 8 bit int. See that the received value is the same than the one
+ in the field */
+
+static int get_uint8_equal(QEMUFile *f, void *pv, size_t size)
+{
+ uint8_t *v = pv;
+ uint8_t v2;
+ qemu_get_8s(f, &v2);
+
+ if (*v == v2)
+ return 0;
+ return -EINVAL;
+}
+
+const VMStateInfo vmstate_info_uint8_equal = {
+ .name = "int32 equal",
+ .get = get_uint8_equal,
+ .put = put_uint8,
+};
+
/* timers */
static int get_timer(QEMUFile *f, void *pv, size_t size)
return 0;
}
-void vmstate_unregister(const char *idstr, void *opaque)
+void vmstate_unregister(const VMStateDescription *vmsd, void *opaque)
{
- unregister_savevm(idstr, opaque);
+ SaveStateEntry *se, *new_se;
+
+ TAILQ_FOREACH_SAFE(se, &savevm_handlers, entry, new_se) {
+ if (se->vmsd == vmsd && se->opaque == opaque) {
+ TAILQ_REMOVE(&savevm_handlers, se, entry);
+ qemu_free(se);
+ }
+ }
}
int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
if (version_id < vmsd->minimum_version_id) {
return vmsd->load_state_old(f, opaque, version_id);
}
+ if (vmsd->pre_load) {
+ int ret = vmsd->pre_load(opaque);
+ if (ret)
+ return ret;
+ }
while(field->name) {
if (field->version_id <= version_id) {
void *base_addr = opaque + field->offset;
}
field++;
}
- if (vmsd->run_after_load)
- return vmsd->run_after_load(opaque);
+ if (vmsd->post_load) {
+ return vmsd->post_load(opaque);
+ }
return 0;
}
{
VMStateField *field = vmsd->fields;
+ if (vmsd->pre_save) {
+ vmsd->pre_save(opaque);
+ }
while(field->name) {
const void *base_addr = opaque + field->offset;
int i, n_elems = 1;
}
field++;
}
+ if (vmsd->post_save) {
+ vmsd->post_save(opaque);
+ }
}
static int vmstate_load(QEMUFile *f, SaveStateEntry *se, int version_id)
}
typedef struct LoadStateEntry {
+ LIST_ENTRY(LoadStateEntry) entry;
SaveStateEntry *se;
int section_id;
int version_id;
- struct LoadStateEntry *next;
} LoadStateEntry;
-static int qemu_loadvm_state_v2(QEMUFile *f)
-{
- SaveStateEntry *se;
- int len, ret, instance_id, record_len, version_id;
- int64_t total_len, end_pos, cur_pos;
- char idstr[256];
-
- total_len = qemu_get_be64(f);
- end_pos = total_len + qemu_ftell(f);
- for(;;) {
- if (qemu_ftell(f) >= end_pos)
- break;
- len = qemu_get_byte(f);
- qemu_get_buffer(f, (uint8_t *)idstr, len);
- idstr[len] = '\0';
- instance_id = qemu_get_be32(f);
- version_id = qemu_get_be32(f);
- record_len = qemu_get_be32(f);
- cur_pos = qemu_ftell(f);
- se = find_se(idstr, instance_id);
- if (!se) {
- fprintf(stderr, "qemu: warning: instance 0x%x of device '%s' not present in current VM\n",
- instance_id, idstr);
- } else {
- ret = vmstate_load(f, se, version_id);
- if (ret < 0) {
- fprintf(stderr, "qemu: warning: error while loading state for instance 0x%x of device '%s'\n",
- instance_id, idstr);
- return ret;
- }
- }
- /* always seek to exact end of record */
- qemu_fseek(f, cur_pos + record_len, SEEK_SET);
- }
-
- if (qemu_file_has_error(f))
- return -EIO;
-
- return 0;
-}
-
int qemu_loadvm_state(QEMUFile *f)
{
- LoadStateEntry *first_le = NULL;
+ LIST_HEAD(, LoadStateEntry) loadvm_handlers =
+ LIST_HEAD_INITIALIZER(loadvm_handlers);
+ LoadStateEntry *le, *new_le;
uint8_t section_type;
unsigned int v;
int ret;
return -EINVAL;
v = qemu_get_be32(f);
- if (v == QEMU_VM_FILE_VERSION_COMPAT)
- return qemu_loadvm_state_v2(f);
+ if (v == QEMU_VM_FILE_VERSION_COMPAT) {
+ fprintf(stderr, "SaveVM v2 format is obsolete and don't work anymore\n");
+ return -ENOTSUP;
+ }
if (v != QEMU_VM_FILE_VERSION)
return -ENOTSUP;
while ((section_type = qemu_get_byte(f)) != QEMU_VM_EOF) {
uint32_t instance_id, version_id, section_id;
- LoadStateEntry *le;
SaveStateEntry *se;
char idstr[257];
int len;
le->se = se;
le->section_id = section_id;
le->version_id = version_id;
- le->next = first_le;
- first_le = le;
+ LIST_INSERT_HEAD(&loadvm_handlers, le, entry);
ret = vmstate_load(f, le->se, le->version_id);
if (ret < 0) {
case QEMU_VM_SECTION_END:
section_id = qemu_get_be32(f);
- for (le = first_le; le && le->section_id != section_id; le = le->next);
+ LIST_FOREACH(le, &loadvm_handlers, entry) {
+ if (le->section_id == section_id) {
+ break;
+ }
+ }
if (le == NULL) {
fprintf(stderr, "Unknown savevm section %d\n", section_id);
ret = -EINVAL;
ret = 0;
out:
- while (first_le) {
- LoadStateEntry *le = first_le;
- first_le = first_le->next;
+ LIST_FOREACH_SAFE(le, &loadvm_handlers, entry, new_le) {
+ LIST_REMOVE(le, entry);
qemu_free(le);
}