diff options
author | Stefan Hajnoczi <stefanha@redhat.com> | 2018-08-16 14:05:28 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2018-08-16 14:05:28 +0100 |
commit | e2336043cc40eafc302c5ea8fa1d5c01438c06bb (patch) | |
tree | d589482e4c455931bb5fe845209d2678839c9116 /hw/core | |
parent | e7f59933548097dbb2272c49f2e0a4ece92697ff (diff) | |
download | qemu-e2336043cc40eafc302c5ea8fa1d5c01438c06bb.zip |
loader: add rom transaction API
Image file loaders may add a series of roms. If an error occurs partway
through loading there is no easy way to drop previously added roms.
This patch adds a transaction mechanism that works like this:
rom_transaction_begin();
...call rom_add_*()...
rom_transaction_end(ok);
If ok is false then roms added in this transaction are dropped.
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Message-id: 20180814162739.11814-5-stefanha@redhat.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/core')
-rw-r--r-- | hw/core/loader.c | 32 |
1 files changed, 32 insertions, 0 deletions
diff --git a/hw/core/loader.c b/hw/core/loader.c index 0c72e7c05a..612420b870 100644 --- a/hw/core/loader.c +++ b/hw/core/loader.c @@ -840,6 +840,8 @@ struct Rom { char *fw_dir; char *fw_file; + bool committed; + hwaddr addr; QTAILQ_ENTRY(Rom) next; }; @@ -877,6 +879,8 @@ static void rom_insert(Rom *rom) rom->as = &address_space_memory; } + rom->committed = false; + /* List is ordered by load address in the same address space */ QTAILQ_FOREACH(item, &roms, next) { if (rom_order_compare(rom, item)) { @@ -1168,6 +1172,34 @@ void rom_reset_order_override(void) fw_cfg_reset_order_override(fw_cfg); } +void rom_transaction_begin(void) +{ + Rom *rom; + + /* Ignore ROMs added without the transaction API */ + QTAILQ_FOREACH(rom, &roms, next) { + rom->committed = true; + } +} + +void rom_transaction_end(bool commit) +{ + Rom *rom; + Rom *tmp; + + QTAILQ_FOREACH_SAFE(rom, &roms, next, tmp) { + if (rom->committed) { + continue; + } + if (commit) { + rom->committed = true; + } else { + QTAILQ_REMOVE(&roms, rom, next); + rom_free(rom); + } + } +} + static Rom *find_rom(hwaddr addr, size_t size) { Rom *rom; |