mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-15 06:01:58 -06:00
hw/mips/boston: Support dumpdtb monitor commands
The boston machine doesn't set MachineState::fdt to the DTB blob that it has loaded or created, which means that the QMP/HMP dumpdtb monitor commands don't work. Setting MachineState::fdt is easy in the non-FIT codepath: we can simply do so immediately before loading the DTB into guest memory. The FIT codepath is a bit more awkward as currently the FIT loader throws away the memory that the FDT was in after it loads it into guest memory. So we add a void *pfdt argument to load_fit() for it to store the FDT pointer into. There is some readjustment required of the pointer handling in loader-fit.c, so that it applies 'const' only where it should (e.g. the data pointer we get back from fdt_getprop() is const, because it's into the middle of the input FDT data, but the pointer that fit_load_image_alloc() should not be const, because it's freshly allocated memory that the caller can change if it likes). Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Message-id: 20250206151214.2947842-5-peter.maydell@linaro.org
This commit is contained in:
parent
dfd0de7186
commit
db0dd33559
3 changed files with 46 additions and 24 deletions
|
@ -32,7 +32,7 @@
|
|||
|
||||
#define FIT_LOADER_MAX_PATH (128)
|
||||
|
||||
static const void *fit_load_image_alloc(const void *itb, const char *name,
|
||||
static void *fit_load_image_alloc(const void *itb, const char *name,
|
||||
int *poff, size_t *psz, Error **errp)
|
||||
{
|
||||
const void *data;
|
||||
|
@ -80,11 +80,11 @@ static const void *fit_load_image_alloc(const void *itb, const char *name,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
data = g_realloc(uncomp_data, uncomp_len);
|
||||
uncomp_data = g_realloc(uncomp_data, uncomp_len);
|
||||
if (psz) {
|
||||
*psz = uncomp_len;
|
||||
}
|
||||
return data;
|
||||
return uncomp_data;
|
||||
}
|
||||
|
||||
error_setg(errp, "unknown compression '%s'", comp);
|
||||
|
@ -177,13 +177,12 @@ out:
|
|||
|
||||
static int fit_load_fdt(const struct fit_loader *ldr, const void *itb,
|
||||
int cfg, void *opaque, const void *match_data,
|
||||
hwaddr kernel_end, Error **errp)
|
||||
hwaddr kernel_end, void **pfdt, Error **errp)
|
||||
{
|
||||
ERRP_GUARD();
|
||||
Error *err = NULL;
|
||||
const char *name;
|
||||
const void *data;
|
||||
const void *load_data;
|
||||
void *data;
|
||||
hwaddr load_addr;
|
||||
int img_off;
|
||||
size_t sz;
|
||||
|
@ -194,7 +193,7 @@ static int fit_load_fdt(const struct fit_loader *ldr, const void *itb,
|
|||
return 0;
|
||||
}
|
||||
|
||||
load_data = data = fit_load_image_alloc(itb, name, &img_off, &sz, errp);
|
||||
data = fit_load_image_alloc(itb, name, &img_off, &sz, errp);
|
||||
if (!data) {
|
||||
error_prepend(errp, "unable to load FDT image from FIT: ");
|
||||
return -EINVAL;
|
||||
|
@ -211,19 +210,23 @@ static int fit_load_fdt(const struct fit_loader *ldr, const void *itb,
|
|||
}
|
||||
|
||||
if (ldr->fdt_filter) {
|
||||
load_data = ldr->fdt_filter(opaque, data, match_data, &load_addr);
|
||||
void *filtered_data;
|
||||
|
||||
filtered_data = ldr->fdt_filter(opaque, data, match_data, &load_addr);
|
||||
if (filtered_data != data) {
|
||||
g_free(data);
|
||||
data = filtered_data;
|
||||
}
|
||||
}
|
||||
|
||||
load_addr = ldr->addr_to_phys(opaque, load_addr);
|
||||
sz = fdt_totalsize(load_data);
|
||||
rom_add_blob_fixed(name, load_data, sz, load_addr);
|
||||
sz = fdt_totalsize(data);
|
||||
rom_add_blob_fixed(name, data, sz, load_addr);
|
||||
|
||||
ret = 0;
|
||||
*pfdt = data;
|
||||
return 0;
|
||||
out:
|
||||
g_free((void *) data);
|
||||
if (data != load_data) {
|
||||
g_free((void *) load_data);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -259,7 +262,8 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
int load_fit(const struct fit_loader *ldr, const char *filename, void *opaque)
|
||||
int load_fit(const struct fit_loader *ldr, const char *filename,
|
||||
void **pfdt, void *opaque)
|
||||
{
|
||||
Error *err = NULL;
|
||||
const struct fit_loader_match *match;
|
||||
|
@ -323,7 +327,7 @@ int load_fit(const struct fit_loader *ldr, const char *filename, void *opaque)
|
|||
goto out;
|
||||
}
|
||||
|
||||
ret = fit_load_fdt(ldr, itb, cfg_off, opaque, match_data, kernel_end,
|
||||
ret = fit_load_fdt(ldr, itb, cfg_off, opaque, match_data, kernel_end, pfdt,
|
||||
&err);
|
||||
if (ret) {
|
||||
error_report_err(err);
|
||||
|
|
|
@ -358,7 +358,7 @@ static void gen_firmware(void *p, hwaddr kernel_entry, hwaddr fdt_addr)
|
|||
kernel_entry);
|
||||
}
|
||||
|
||||
static const void *boston_fdt_filter(void *opaque, const void *fdt_orig,
|
||||
static void *boston_fdt_filter(void *opaque, const void *fdt_orig,
|
||||
const void *match_data, hwaddr *load_addr)
|
||||
{
|
||||
BostonState *s = BOSTON(opaque);
|
||||
|
@ -797,7 +797,7 @@ static void boston_mach_init(MachineState *machine)
|
|||
if (kernel_size > 0) {
|
||||
int dt_size;
|
||||
g_autofree const void *dtb_file_data = NULL;
|
||||
g_autofree const void *dtb_load_data = NULL;
|
||||
void *dtb_load_data = NULL;
|
||||
hwaddr dtb_paddr = QEMU_ALIGN_UP(kernel_high, 64 * KiB);
|
||||
hwaddr dtb_vaddr = cpu_mips_phys_to_kseg0(NULL, dtb_paddr);
|
||||
|
||||
|
@ -815,6 +815,8 @@ static void boston_mach_init(MachineState *machine)
|
|||
exit(1);
|
||||
}
|
||||
|
||||
machine->fdt = dtb_load_data;
|
||||
|
||||
/* Calculate real fdt size after filter */
|
||||
dt_size = fdt_totalsize(dtb_load_data);
|
||||
rom_add_blob_fixed("dtb", dtb_load_data, dt_size, dtb_paddr);
|
||||
|
@ -822,7 +824,8 @@ static void boston_mach_init(MachineState *machine)
|
|||
rom_ptr(dtb_paddr, dt_size));
|
||||
} else {
|
||||
/* Try to load file as FIT */
|
||||
fit_err = load_fit(&boston_fit_loader, machine->kernel_filename, s);
|
||||
fit_err = load_fit(&boston_fit_loader, machine->kernel_filename,
|
||||
&machine->fdt, s);
|
||||
if (fit_err) {
|
||||
error_report("unable to load kernel image");
|
||||
exit(1);
|
||||
|
|
|
@ -30,12 +30,27 @@ struct fit_loader_match {
|
|||
struct fit_loader {
|
||||
const struct fit_loader_match *matches;
|
||||
hwaddr (*addr_to_phys)(void *opaque, uint64_t addr);
|
||||
const void *(*fdt_filter)(void *opaque, const void *fdt,
|
||||
void *(*fdt_filter)(void *opaque, const void *fdt,
|
||||
const void *match_data, hwaddr *load_addr);
|
||||
const void *(*kernel_filter)(void *opaque, const void *kernel,
|
||||
hwaddr *load_addr, hwaddr *entry_addr);
|
||||
};
|
||||
|
||||
int load_fit(const struct fit_loader *ldr, const char *filename, void *opaque);
|
||||
/**
|
||||
* load_fit: load a FIT format image
|
||||
* @ldr: structure defining board specific properties and hooks
|
||||
* @filename: image to load
|
||||
* @pfdt: pointer to update with address of FDT blob
|
||||
* @opaque: opaque value passed back to the hook functions in @ldr
|
||||
* Returns: 0 on success, or a negative errno on failure
|
||||
*
|
||||
* @pfdt is used to tell the caller about the FDT blob. On return, it
|
||||
* has been set to point to the FDT blob, and it is now the caller's
|
||||
* responsibility to free that memory with g_free(). Usually the caller
|
||||
* will want to pass in &machine->fdt here, to record the FDT blob for
|
||||
* the dumpdtb option and QMP/HMP commands.
|
||||
*/
|
||||
int load_fit(const struct fit_loader *ldr, const char *filename, void **pfdt,
|
||||
void *opaque);
|
||||
|
||||
#endif /* HW_LOADER_FIT_H */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue