hw/arm/boot: Make write_bootloader() public as arm_write_bootloader()

The arm boot.c code includes a utility function write_bootloader()
which assists in writing a boot-code fragment into guest memory,
including handling endianness and fixing it up with entry point
addresses and similar things.  This is useful not just for the boot.c
code but also in board model code, so rename it to
arm_write_bootloader() and make it globally visible.

Since we are making it public, make its API a little neater: move the
AddressSpace* argument to be next to the hwaddr argument, and allow
the fixupcontext array to be const, since we never modify it in this
function.

Cc: qemu-stable@nongnu.org
Signed-off-by: Cédric Le Goater <clg@kaod.org>
Tested-by: Cédric Le Goater <clg@kaod.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 20230424152717.1333930-2-peter.maydell@linaro.org
[PMM: Split out from another patch by Cédric, added doc comment]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
(cherry picked from commit 0fe43f0abf19bbe24df3dbf0613bb47ed55f1482)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
This commit is contained in:
Cédric Le Goater 2023-04-24 16:27:15 +01:00 committed by Michael Tokarev
parent e96dc26e89
commit 8e9c265f14
2 changed files with 57 additions and 27 deletions

View file

@ -59,26 +59,6 @@ AddressSpace *arm_boot_address_space(ARMCPU *cpu,
return cpu_get_address_space(cs, asidx);
}
typedef enum {
FIXUP_NONE = 0, /* do nothing */
FIXUP_TERMINATOR, /* end of insns */
FIXUP_BOARDID, /* overwrite with board ID number */
FIXUP_BOARD_SETUP, /* overwrite with board specific setup code address */
FIXUP_ARGPTR_LO, /* overwrite with pointer to kernel args */
FIXUP_ARGPTR_HI, /* overwrite with pointer to kernel args (high half) */
FIXUP_ENTRYPOINT_LO, /* overwrite with kernel entry point */
FIXUP_ENTRYPOINT_HI, /* overwrite with kernel entry point (high half) */
FIXUP_GIC_CPU_IF, /* overwrite with GIC CPU interface address */
FIXUP_BOOTREG, /* overwrite with boot register address */
FIXUP_DSB, /* overwrite with correct DSB insn for cpu */
FIXUP_MAX,
} FixupType;
typedef struct ARMInsnFixup {
uint32_t insn;
FixupType fixup;
} ARMInsnFixup;
static const ARMInsnFixup bootloader_aarch64[] = {
{ 0x580000c0 }, /* ldr x0, arg ; Load the lower 32-bits of DTB */
{ 0xaa1f03e1 }, /* mov x1, xzr */
@ -149,9 +129,10 @@ static const ARMInsnFixup smpboot[] = {
{ 0, FIXUP_TERMINATOR }
};
static void write_bootloader(const char *name, hwaddr addr,
const ARMInsnFixup *insns, uint32_t *fixupcontext,
AddressSpace *as)
void arm_write_bootloader(const char *name,
AddressSpace *as, hwaddr addr,
const ARMInsnFixup *insns,
const uint32_t *fixupcontext)
{
/* Fix up the specified bootloader fragment and write it into
* guest memory using rom_add_blob_fixed(). fixupcontext is
@ -213,8 +194,8 @@ static void default_write_secondary(ARMCPU *cpu,
fixupcontext[FIXUP_DSB] = CP15_DSB_INSN;
}
write_bootloader("smpboot", info->smp_loader_start,
smpboot, fixupcontext, as);
arm_write_bootloader("smpboot", as, info->smp_loader_start,
smpboot, fixupcontext);
}
void arm_write_secure_board_setup_dummy_smc(ARMCPU *cpu,
@ -1174,8 +1155,8 @@ static void arm_setup_direct_kernel_boot(ARMCPU *cpu,
fixupcontext[FIXUP_ENTRYPOINT_LO] = entry;
fixupcontext[FIXUP_ENTRYPOINT_HI] = entry >> 32;
write_bootloader("bootloader", info->loader_start,
primary_loader, fixupcontext, as);
arm_write_bootloader("bootloader", as, info->loader_start,
primary_loader, fixupcontext);
if (info->write_board_setup) {
info->write_board_setup(cpu, info);

View file

@ -183,4 +183,53 @@ void arm_write_secure_board_setup_dummy_smc(ARMCPU *cpu,
const struct arm_boot_info *info,
hwaddr mvbar_addr);
typedef enum {
FIXUP_NONE = 0, /* do nothing */
FIXUP_TERMINATOR, /* end of insns */
FIXUP_BOARDID, /* overwrite with board ID number */
FIXUP_BOARD_SETUP, /* overwrite with board specific setup code address */
FIXUP_ARGPTR_LO, /* overwrite with pointer to kernel args */
FIXUP_ARGPTR_HI, /* overwrite with pointer to kernel args (high half) */
FIXUP_ENTRYPOINT_LO, /* overwrite with kernel entry point */
FIXUP_ENTRYPOINT_HI, /* overwrite with kernel entry point (high half) */
FIXUP_GIC_CPU_IF, /* overwrite with GIC CPU interface address */
FIXUP_BOOTREG, /* overwrite with boot register address */
FIXUP_DSB, /* overwrite with correct DSB insn for cpu */
FIXUP_MAX,
} FixupType;
typedef struct ARMInsnFixup {
uint32_t insn;
FixupType fixup;
} ARMInsnFixup;
/**
* arm_write_bootloader - write a bootloader to guest memory
* @name: name of the bootloader blob
* @as: AddressSpace to write the bootloader
* @addr: guest address to write it
* @insns: the blob to be loaded
* @fixupcontext: context to be used for any fixups in @insns
*
* Write a bootloader to guest memory at address @addr in the address
* space @as. @name is the name to use for the resulting ROM blob, so
* it should be unique in the system and reasonably identifiable for debugging.
*
* @insns must be an array of ARMInsnFixup structs, each of which has
* one 32-bit value to be written to the guest memory, and a fixup to be
* applied to the value. FIXUP_NONE (do nothing) is value 0, so effectively
* the fixup is optional when writing a struct initializer.
* The final entry in the array must be { 0, FIXUP_TERMINATOR }.
*
* All other supported fixup types have the semantics "ignore insn
* and instead use the value from the array element @fixupcontext[fixup]".
* The caller should therefore provide @fixupcontext as an array of
* size FIXUP_MAX whose elements have been initialized for at least
* the entries that @insns refers to.
*/
void arm_write_bootloader(const char *name,
AddressSpace *as, hwaddr addr,
const ARMInsnFixup *insns,
const uint32_t *fixupcontext);
#endif /* HW_ARM_BOOT_H */