[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 1/3] loader: add support for resizeable blobs
From: |
Michael S. Tsirkin |
Subject: |
[Qemu-devel] [PATCH 1/3] loader: add support for resizeable blobs |
Date: |
Mon, 28 Jul 2014 17:35:04 +0200 |
Support resizeable blobs: we allocate more memory than currently
available in the blob, which can later be filled in.
Signed-off-by: Michael S. Tsirkin <address@hidden>
---
include/hw/loader.h | 14 +++++++--
include/hw/nvram/fw_cfg.h | 2 +-
hw/core/loader.c | 15 +++++----
hw/nvram/fw_cfg.c | 79 ++++++++++++++++++++++++++++++++++++++++++++---
4 files changed, 96 insertions(+), 14 deletions(-)
diff --git a/include/hw/loader.h b/include/hw/loader.h
index 796cbf9..ecce654 100644
--- a/include/hw/loader.h
+++ b/include/hw/loader.h
@@ -55,9 +55,19 @@ extern bool rom_file_has_mr;
int rom_add_file(const char *file, const char *fw_dir,
hwaddr addr, int32_t bootindex,
bool option_rom);
-void *rom_add_blob(const char *name, const void *blob, size_t len,
+void *rom_add_blob_resizeable(const char *name, const void *blob,
+ size_t len, size_t max_len,
+ hwaddr addr, const char *fw_file_name,
+ FWCfgReadCallback fw_callback,
+ void *callback_opaque);
+static inline void *rom_add_blob(const char *name, const void *blob, size_t
len,
hwaddr addr, const char *fw_file_name,
- FWCfgReadCallback fw_callback, void *callback_opaque);
+ FWCfgReadCallback fw_callback, void *callback_opaque)
+{
+ return rom_add_blob_resizeable(name, blob, len, len, addr,
+ fw_file_name, fw_callback, callback_opaque);
+}
+
int rom_add_elf_program(const char *name, void *data, size_t datasize,
size_t romsize, hwaddr addr);
int rom_load_all(void);
diff --git a/include/hw/nvram/fw_cfg.h b/include/hw/nvram/fw_cfg.h
index 72b1549..da4f5c5 100644
--- a/include/hw/nvram/fw_cfg.h
+++ b/include/hw/nvram/fw_cfg.h
@@ -75,7 +75,7 @@ void fw_cfg_add_file(FWCfgState *s, const char *filename,
void *data,
size_t len);
void fw_cfg_add_file_callback(FWCfgState *s, const char *filename,
FWCfgReadCallback callback, void
*callback_opaque,
- void *data, size_t len);
+ void *data, size_t len, size_t max_len);
FWCfgState *fw_cfg_init(uint32_t ctl_port, uint32_t data_port,
hwaddr crl_addr, hwaddr data_addr);
diff --git a/hw/core/loader.c b/hw/core/loader.c
index 2bf6b8f..ad6ec67 100644
--- a/hw/core/loader.c
+++ b/hw/core/loader.c
@@ -720,9 +720,11 @@ err:
return -1;
}
-void *rom_add_blob(const char *name, const void *blob, size_t len,
- hwaddr addr, const char *fw_file_name,
- FWCfgReadCallback fw_callback, void *callback_opaque)
+void *rom_add_blob_resizeable(const char *name, const void *blob,
+ size_t len, size_t max_len,
+ hwaddr addr, const char *fw_file_name,
+ FWCfgReadCallback fw_callback,
+ void *callback_opaque)
{
Rom *rom;
void *data = NULL;
@@ -730,9 +732,10 @@ void *rom_add_blob(const char *name, const void *blob,
size_t len,
rom = g_malloc0(sizeof(*rom));
rom->name = g_strdup(name);
rom->addr = addr;
- rom->romsize = len;
- rom->datasize = len;
+ rom->romsize = max_len;
+ rom->datasize = max_len;
rom->data = g_malloc0(rom->datasize);
+ assert(len <= rom->datasize);
memcpy(rom->data, blob, len);
rom_insert(rom);
if (fw_file_name && fw_cfg) {
@@ -748,7 +751,7 @@ void *rom_add_blob(const char *name, const void *blob,
size_t len,
fw_cfg_add_file_callback(fw_cfg, fw_file_name,
fw_callback, callback_opaque,
- data, rom->romsize);
+ data, rom->romsize, rom->datasize);
}
return data;
}
diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c
index b71d251..65f233e 100644
--- a/hw/nvram/fw_cfg.c
+++ b/hw/nvram/fw_cfg.c
@@ -38,6 +38,8 @@
#define FW_CFG(obj) OBJECT_CHECK(FWCfgState, (obj), TYPE_FW_CFG)
typedef struct FWCfgEntry {
+ uint32_t max_len;
+ uint32_t reset_len;
uint32_t len;
uint8_t *data;
void *callback_opaque;
@@ -57,6 +59,9 @@ struct FWCfgState {
uint16_t cur_entry;
uint32_t cur_offset;
Notifier machine_ready;
+ /* Entry length: used for migration */
+#define FW_CFG_LEN_ENTRIES (2 * FW_CFG_MAX_ENTRY)
+ uint32_t len[FW_CFG_LEN_ENTRIES];
};
#define JPG_FILE 0
@@ -336,6 +341,13 @@ static const MemoryRegionOps fw_cfg_comb_mem_ops = {
static void fw_cfg_reset(DeviceState *d)
{
FWCfgState *s = FW_CFG(d);
+ int i, j;
+
+ for (i = 0; i < ARRAY_SIZE(s->entries); ++i) {
+ for (j = 0; j < ARRAY_SIZE(s->entries[0]); ++j) {
+ s->entries[i][j].len = s->entries[i][j].reset_len;
+ }
+ }
fw_cfg_select(s, 0);
}
@@ -373,14 +385,63 @@ static bool is_version_1(void *opaque, int version_id)
return version_id == 1;
}
+static void fw_cfg_pre_save(void *opaque)
+{
+ FWCfgState *s = FW_CFG(opaque);
+ int i, j;
+
+ for (i = 0; i < ARRAY_SIZE(s->entries); ++i) {
+ for (j = 0; j < ARRAY_SIZE(s->entries[0]); ++j) {
+ s->len[i * j] = s->entries[i][j].len;
+ }
+ }
+}
+
+static int fw_cfg_post_load(void *opaque, int version_id)
+{
+ FWCfgState *s = FW_CFG(opaque);
+ int i, j;
+
+ for (i = 0; i < ARRAY_SIZE(s->entries); ++i) {
+ for (j = 0; j < ARRAY_SIZE(s->entries[0]); ++j) {
+ if (s->entries[i][j].max_len < s->len[i * j]) {
+ return -1;
+ }
+ s->entries[i][j].len = s->len[i * j];
+ }
+ }
+ return 0;
+}
+
+static bool fw_cfg_len_needed(void *opaque, int version_id)
+{
+ FWCfgState *s = FW_CFG(opaque);
+ int i, j;
+
+ for (i = 0; i < ARRAY_SIZE(s->entries); ++i) {
+ for (j = 0; j < ARRAY_SIZE(s->entries[0]); ++j) {
+ if (s->entries[i][j].len != s->entries[i][j].max_len) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
static const VMStateDescription vmstate_fw_cfg = {
.name = "fw_cfg",
.version_id = 2,
.minimum_version_id = 1,
+ .post_load = fw_cfg_post_load,
+ .pre_save = fw_cfg_pre_save,
.fields = (VMStateField[]) {
VMSTATE_UINT16(cur_entry, FWCfgState),
VMSTATE_UINT16_HACK(cur_offset, FWCfgState, is_version_1),
VMSTATE_UINT32_V(cur_offset, FWCfgState, 2),
+ VMSTATE_ARRAY_TEST(len, FWCfgState, FW_CFG_LEN_ENTRIES,
+ fw_cfg_len_needed,
+ vmstate_info_uint32, uint32_t),
VMSTATE_END_OF_LIST()
}
};
@@ -388,23 +449,28 @@ static const VMStateDescription vmstate_fw_cfg = {
static void fw_cfg_add_bytes_read_callback(FWCfgState *s, uint16_t key,
FWCfgReadCallback callback,
void *callback_opaque,
- void *data, size_t len)
+ void *data, size_t len,
+ size_t max_len)
{
int arch = !!(key & FW_CFG_ARCH_LOCAL);
+ assert(len <= max_len);
+
key &= FW_CFG_ENTRY_MASK;
assert(key < FW_CFG_MAX_ENTRY && len < UINT32_MAX);
s->entries[arch][key].data = data;
s->entries[arch][key].len = (uint32_t)len;
+ s->entries[arch][key].reset_len = (uint32_t)len;
+ s->entries[arch][key].max_len = (uint32_t)max_len;
s->entries[arch][key].read_callback = callback;
s->entries[arch][key].callback_opaque = callback_opaque;
}
void fw_cfg_add_bytes(FWCfgState *s, uint16_t key, void *data, size_t len)
{
- fw_cfg_add_bytes_read_callback(s, key, NULL, NULL, data, len);
+ fw_cfg_add_bytes_read_callback(s, key, NULL, NULL, data, len, len);
}
void fw_cfg_add_string(FWCfgState *s, uint16_t key, const char *value)
@@ -454,13 +520,15 @@ void fw_cfg_add_callback(FWCfgState *s, uint16_t key,
FWCfgCallback callback,
s->entries[arch][key].data = data;
s->entries[arch][key].len = (uint32_t)len;
+ s->entries[arch][key].reset_len = (uint32_t)len;
+ s->entries[arch][key].max_len = (uint32_t)len;
s->entries[arch][key].callback_opaque = callback_opaque;
s->entries[arch][key].callback = callback;
}
void fw_cfg_add_file_callback(FWCfgState *s, const char *filename,
FWCfgReadCallback callback, void
*callback_opaque,
- void *data, size_t len)
+ void *data, size_t len, size_t max_len)
{
int i, index;
size_t dsize;
@@ -475,7 +543,8 @@ void fw_cfg_add_file_callback(FWCfgState *s, const char
*filename,
assert(index < FW_CFG_FILE_SLOTS);
fw_cfg_add_bytes_read_callback(s, FW_CFG_FILE_FIRST + index,
- callback, callback_opaque, data, len);
+ callback, callback_opaque, data, len,
+ max_len);
pstrcpy(s->files->f[index].name, sizeof(s->files->f[index].name),
filename);
@@ -496,7 +565,7 @@ void fw_cfg_add_file_callback(FWCfgState *s, const char
*filename,
void fw_cfg_add_file(FWCfgState *s, const char *filename,
void *data, size_t len)
{
- fw_cfg_add_file_callback(s, filename, NULL, NULL, data, len);
+ fw_cfg_add_file_callback(s, filename, NULL, NULL, data, len, len);
}
static void fw_cfg_machine_ready(struct Notifier *n, void *data)
--
MST
- [Qemu-devel] [PATCH 1/3] loader: add support for resizeable blobs,
Michael S. Tsirkin <=