From: "Michael S. Tsirkin" <mst@redhat.com>
To: qemu-devel@nongnu.org
Cc: "Alexey Kardashevskiy" <aik@ozlabs.ru>,
"Alexander Graf" <agraf@suse.de>,
"Markus Armbruster" <armbru@redhat.com>,
"Gerd Hoffmann" <kraxel@redhat.com>,
imammedo@redhat.com, pbonzini@redhat.com,
"Laszlo Ersek" <lersek@redhat.com>,
=?UTF-8?q?Andreas=20F=C3=A4rber?= <afaerber@suse.de>
Subject: [Qemu-devel] [PATCH 1/3] loader: add support for resizeable blobs
Date: Mon, 28 Jul 2014 17:35:04 +0200 [thread overview]
Message-ID: <1406561650-29995-1-git-send-email-mst@redhat.com> (raw)
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 <mst@redhat.com>
---
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
next reply other threads:[~2014-07-28 15:35 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-07-28 15:35 Michael S. Tsirkin [this message]
2014-07-28 15:35 ` [Qemu-devel] [PATCH 2/3] migration: load smaller RAMBlock to a bigger one if permitted Michael S. Tsirkin
2014-07-28 15:35 ` [Qemu-devel] [PATCH 3/3] loader: mark MR for resizeable blobs as extendable Michael S. Tsirkin
2014-07-28 16:52 ` [Qemu-devel] [PATCH 1/3] loader: add support for resizeable blobs Dr. David Alan Gilbert
2014-07-28 19:07 ` Michael S. Tsirkin
2014-07-28 19:20 ` Paolo Bonzini
2014-07-29 8:02 ` Dr. David Alan Gilbert
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1406561650-29995-1-git-send-email-mst@redhat.com \
--to=mst@redhat.com \
--cc=afaerber@suse.de \
--cc=agraf@suse.de \
--cc=aik@ozlabs.ru \
--cc=armbru@redhat.com \
--cc=imammedo@redhat.com \
--cc=kraxel@redhat.com \
--cc=lersek@redhat.com \
--cc=pbonzini@redhat.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).