From: Ben Warren ben@skyportsystems.com
The command allows the memory allocation of a fw_cfg file by BIOS and subsequent return of the allocated address to QEMU.
Signed-off-by: Ben Warren ben@skyportsystems.com --- src/fw/romfile_loader.c | 38 ++++++++++++++++++++++++++++++++++++++ src/fw/romfile_loader.h | 23 ++++++++++++++++++++--- 2 files changed, 58 insertions(+), 3 deletions(-)
diff --git a/src/fw/romfile_loader.c b/src/fw/romfile_loader.c index f4b17ff..1b3fb3e 100644 --- a/src/fw/romfile_loader.c +++ b/src/fw/romfile_loader.c @@ -5,6 +5,7 @@ #include "romfile.h" // struct romfile_s #include "malloc.h" // Zone*, _malloc #include "output.h" // warn_* +#include "paravirt.h" // qemu_cfg_write_file
struct romfile_loader_file { struct romfile_s *file; @@ -127,6 +128,38 @@ err: warn_internalerror(); }
+static void romfile_loader_return_addr(struct romfile_loader_entry_s *entry, + struct romfile_loader_files *files) +{ + struct romfile_loader_file *alloc_file; + struct romfile_loader_file *addr_file; + u64 addr; + int ret; + + alloc_file = romfile_loader_find(entry->alloc_ret_file, files); + addr_file = romfile_loader_find(entry->alloc_ret_addr_file, files); + + if (!alloc_file || !addr_file || !alloc_file->data || !addr_file->data || + addr_file->file->size < sizeof(addr)) + goto err; + + /* Get the address of the just-allocated file + * and stuff it in the address file */ + void *data_ptr = alloc_file->data; + + memcpy(&addr, &data_ptr, sizeof(data_ptr)); + addr = cpu_to_le64(addr); + memcpy(addr_file->data, &addr, sizeof(addr)); + + /* Only supported on QEMU */ + ret = qemu_cfg_write_file(&addr, addr_file->file, sizeof(addr)); + if (ret != sizeof(addr)) + goto err; + return; +err: + warn_internalerror(); +} + int romfile_loader_execute(const char *name) { struct romfile_loader_entry_s *entry; @@ -161,6 +194,11 @@ int romfile_loader_execute(const char *name) break; case ROMFILE_LOADER_COMMAND_ADD_CHECKSUM: romfile_loader_add_checksum(entry, files); + break; + case ROMFILE_LOADER_COMMAND_ALLOCATE_RET_ADDR: + romfile_loader_allocate(entry, files); + romfile_loader_return_addr(entry, files); + break; default: /* Skip commands that we don't recognize. */ break; diff --git a/src/fw/romfile_loader.h b/src/fw/romfile_loader.h index 15eab2a..44a6cb8 100644 --- a/src/fw/romfile_loader.h +++ b/src/fw/romfile_loader.h @@ -51,15 +51,32 @@ struct romfile_loader_entry_s { u32 cksum_length; };
+ /* + * COMMAND_ALLOCATE_RETURN_ADDR - allocate a table from @alloc_file + * subject to @alloc_ret_align alignment (must be power of 2) + * and @alloc_ret_zone (can be HIGH or FSEG) requirements. + * Additionally, return the address of the allocation in + * @addr_file. + * + * This may be used instead of COMMAND_ALLOCATE + */ + struct { + char alloc_ret_file[ROMFILE_LOADER_FILESZ]; + u32 alloc_ret_align; + u8 alloc_ret_zone; + char alloc_ret_addr_file[ROMFILE_LOADER_FILESZ]; + }; + /* padding */ char pad[124]; }; };
enum { - ROMFILE_LOADER_COMMAND_ALLOCATE = 0x1, - ROMFILE_LOADER_COMMAND_ADD_POINTER = 0x2, - ROMFILE_LOADER_COMMAND_ADD_CHECKSUM = 0x3, + ROMFILE_LOADER_COMMAND_ALLOCATE = 0x1, + ROMFILE_LOADER_COMMAND_ADD_POINTER = 0x2, + ROMFILE_LOADER_COMMAND_ADD_CHECKSUM = 0x3, + ROMFILE_LOADER_COMMAND_ALLOCATE_RET_ADDR = 0x4, };
enum {