xref: /openbmc/qemu/include/hw/arm/boot.h (revision c586691e676214eb7edf6a468e84e7ce3b314d43)
112ec8bd5SPeter Maydell /*
212ec8bd5SPeter Maydell  * ARM kernel loader.
312ec8bd5SPeter Maydell  *
412ec8bd5SPeter Maydell  * Copyright (c) 2006 CodeSourcery.
512ec8bd5SPeter Maydell  * Written by Paul Brook
612ec8bd5SPeter Maydell  *
712ec8bd5SPeter Maydell  * This code is licensed under the LGPL.
812ec8bd5SPeter Maydell  *
912ec8bd5SPeter Maydell  */
1012ec8bd5SPeter Maydell 
1112ec8bd5SPeter Maydell #ifndef HW_ARM_BOOT_H
1212ec8bd5SPeter Maydell #define HW_ARM_BOOT_H
1312ec8bd5SPeter Maydell 
1412ec8bd5SPeter Maydell #include "target/arm/cpu-qom.h"
1512ec8bd5SPeter Maydell #include "qemu/notify.h"
1612ec8bd5SPeter Maydell 
1712ec8bd5SPeter Maydell typedef enum {
1812ec8bd5SPeter Maydell     ARM_ENDIANNESS_UNKNOWN = 0,
1912ec8bd5SPeter Maydell     ARM_ENDIANNESS_LE,
2012ec8bd5SPeter Maydell     ARM_ENDIANNESS_BE8,
2112ec8bd5SPeter Maydell     ARM_ENDIANNESS_BE32,
2212ec8bd5SPeter Maydell } arm_endianness;
2312ec8bd5SPeter Maydell 
2412ec8bd5SPeter Maydell /**
2512ec8bd5SPeter Maydell  * armv7m_load_kernel:
2612ec8bd5SPeter Maydell  * @cpu: CPU
2712ec8bd5SPeter Maydell  * @kernel_filename: file to load
28761c532aSPeter Maydell  * @mem_base: base address to load image at (should be where the
29761c532aSPeter Maydell  *            CPU expects to find its vector table on reset)
3012ec8bd5SPeter Maydell  * @mem_size: mem_size: maximum image size to load
3112ec8bd5SPeter Maydell  *
3212ec8bd5SPeter Maydell  * Load the guest image for an ARMv7M system. This must be called by
3312ec8bd5SPeter Maydell  * any ARMv7M board. (This is necessary to ensure that the CPU resets
3412ec8bd5SPeter Maydell  * correctly on system reset, as well as for kernel loading.)
3512ec8bd5SPeter Maydell  */
36761c532aSPeter Maydell void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename,
37761c532aSPeter Maydell                         hwaddr mem_base, int mem_size);
3812ec8bd5SPeter Maydell 
3912ec8bd5SPeter Maydell /* arm_boot.c */
4012ec8bd5SPeter Maydell struct arm_boot_info {
4112ec8bd5SPeter Maydell     uint64_t ram_size;
4212ec8bd5SPeter Maydell     const char *kernel_filename;
4312ec8bd5SPeter Maydell     const char *kernel_cmdline;
4412ec8bd5SPeter Maydell     const char *initrd_filename;
4512ec8bd5SPeter Maydell     const char *dtb_filename;
4612ec8bd5SPeter Maydell     hwaddr loader_start;
4712ec8bd5SPeter Maydell     hwaddr dtb_start;
4812ec8bd5SPeter Maydell     hwaddr dtb_limit;
4912ec8bd5SPeter Maydell     /* If set to True, arm_load_kernel() will not load DTB.
5012ec8bd5SPeter Maydell      * It allows board to load DTB manually later.
5112ec8bd5SPeter Maydell      * (default: False)
5212ec8bd5SPeter Maydell      */
5312ec8bd5SPeter Maydell     bool skip_dtb_autoload;
5412ec8bd5SPeter Maydell     /* multicore boards that use the default secondary core boot functions
5512ec8bd5SPeter Maydell      * need to put the address of the secondary boot code, the boot reg,
5612ec8bd5SPeter Maydell      * and the GIC address in the next 3 values, respectively. boards that
5712ec8bd5SPeter Maydell      * have their own boot functions can use these values as they want.
5812ec8bd5SPeter Maydell      */
5912ec8bd5SPeter Maydell     hwaddr smp_loader_start;
6012ec8bd5SPeter Maydell     hwaddr smp_bootreg_addr;
6112ec8bd5SPeter Maydell     hwaddr gic_cpu_if_addr;
6212ec8bd5SPeter Maydell     int board_id;
6312ec8bd5SPeter Maydell     /* ARM machines that support the ARM Security Extensions use this field to
6412ec8bd5SPeter Maydell      * control whether Linux is booted as secure(true) or non-secure(false).
6512ec8bd5SPeter Maydell      */
6612ec8bd5SPeter Maydell     bool secure_boot;
6712ec8bd5SPeter Maydell     int (*atag_board)(const struct arm_boot_info *info, void *p);
6812ec8bd5SPeter Maydell     /* multicore boards that use the default secondary core boot functions
6912ec8bd5SPeter Maydell      * can ignore these two function calls. If the default functions won't
7012ec8bd5SPeter Maydell      * work, then write_secondary_boot() should write a suitable blob of
7112ec8bd5SPeter Maydell      * code mimicking the secondary CPU startup process used by the board's
7212ec8bd5SPeter Maydell      * boot loader/boot ROM code, and secondary_cpu_reset_hook() should
7312ec8bd5SPeter Maydell      * perform any necessary CPU reset handling and set the PC for the
7412ec8bd5SPeter Maydell      * secondary CPUs to point at this boot blob.
75d4a29ed6SPeter Maydell      *
76d4a29ed6SPeter Maydell      * These hooks won't be called if secondary CPUs are booting via
77d4a29ed6SPeter Maydell      * emulated PSCI (see psci_conduit below).
7812ec8bd5SPeter Maydell      */
7912ec8bd5SPeter Maydell     void (*write_secondary_boot)(ARMCPU *cpu,
8012ec8bd5SPeter Maydell                                  const struct arm_boot_info *info);
8112ec8bd5SPeter Maydell     void (*secondary_cpu_reset_hook)(ARMCPU *cpu,
8212ec8bd5SPeter Maydell                                      const struct arm_boot_info *info);
8312ec8bd5SPeter Maydell     /* if a board is able to create a dtb without a dtb file then it
8412ec8bd5SPeter Maydell      * sets get_dtb. This will only be used if no dtb file is provided
8512ec8bd5SPeter Maydell      * by the user. On success, sets *size to the length of the created
8612ec8bd5SPeter Maydell      * dtb, and returns a pointer to it. (The caller must free this memory
8712ec8bd5SPeter Maydell      * with g_free() when it has finished with it.) On failure, returns NULL.
8812ec8bd5SPeter Maydell      */
8912ec8bd5SPeter Maydell     void *(*get_dtb)(const struct arm_boot_info *info, int *size);
9012ec8bd5SPeter Maydell     /* if a board needs to be able to modify a device tree provided by
9112ec8bd5SPeter Maydell      * the user it should implement this hook.
9212ec8bd5SPeter Maydell      */
9312ec8bd5SPeter Maydell     void (*modify_dtb)(const struct arm_boot_info *info, void *fdt);
94817e2db8SPeter Maydell     /*
95817e2db8SPeter Maydell      * If a board wants to use the QEMU emulated-firmware PSCI support,
96817e2db8SPeter Maydell      * it should set this to QEMU_PSCI_CONDUIT_HVC or QEMU_PSCI_CONDUIT_SMC
97817e2db8SPeter Maydell      * as appropriate. arm_load_kernel() will set the psci-conduit and
98817e2db8SPeter Maydell      * start-powered-off properties on the CPUs accordingly.
99817e2db8SPeter Maydell      * Note that if the guest image is started at the same exception level
100817e2db8SPeter Maydell      * as the conduit specifies calls should go to (eg guest firmware booted
101817e2db8SPeter Maydell      * to EL3) then PSCI will not be enabled.
102817e2db8SPeter Maydell      */
103817e2db8SPeter Maydell     int psci_conduit;
10412ec8bd5SPeter Maydell     /* Used internally by arm_boot.c */
10512ec8bd5SPeter Maydell     int is_linux;
10612ec8bd5SPeter Maydell     hwaddr initrd_start;
10712ec8bd5SPeter Maydell     hwaddr initrd_size;
10812ec8bd5SPeter Maydell     hwaddr entry;
10912ec8bd5SPeter Maydell 
11012ec8bd5SPeter Maydell     /* Boot firmware has been loaded, typically at address 0, with -bios or
11112ec8bd5SPeter Maydell      * -pflash. It also implies that fw_cfg_find() will succeed.
11212ec8bd5SPeter Maydell      */
11312ec8bd5SPeter Maydell     bool firmware_loaded;
11412ec8bd5SPeter Maydell 
11512ec8bd5SPeter Maydell     /* Address at which board specific loader/setup code exists. If enabled,
11612ec8bd5SPeter Maydell      * this code-blob will run before anything else. It must return to the
11712ec8bd5SPeter Maydell      * caller via the link register. There is no stack set up. Enabled by
11812ec8bd5SPeter Maydell      * defining write_board_setup, which is responsible for loading the blob
11912ec8bd5SPeter Maydell      * to the specified address.
12012ec8bd5SPeter Maydell      */
12112ec8bd5SPeter Maydell     hwaddr board_setup_addr;
12212ec8bd5SPeter Maydell     void (*write_board_setup)(ARMCPU *cpu,
12312ec8bd5SPeter Maydell                               const struct arm_boot_info *info);
12412ec8bd5SPeter Maydell 
12545c078f1SClement Deschamps     /*
12645c078f1SClement Deschamps      * If set, the board specific loader/setup blob will be run from secure
12712ec8bd5SPeter Maydell      * mode, regardless of secure_boot. The blob becomes responsible for
12845c078f1SClement Deschamps      * changing to non-secure state if implementing a non-secure boot,
12945c078f1SClement Deschamps      * including setting up EL3/Secure registers such as the NSACR as
13045c078f1SClement Deschamps      * required by the Linux booting ABI before the switch to non-secure.
13112ec8bd5SPeter Maydell      */
13212ec8bd5SPeter Maydell     bool secure_board_setup;
13312ec8bd5SPeter Maydell 
13412ec8bd5SPeter Maydell     arm_endianness endianness;
13512ec8bd5SPeter Maydell };
13612ec8bd5SPeter Maydell 
13712ec8bd5SPeter Maydell /**
13812ec8bd5SPeter Maydell  * arm_load_kernel - Loads memory with everything needed to boot
13912ec8bd5SPeter Maydell  *
14012ec8bd5SPeter Maydell  * @cpu: handle to the first CPU object
14112ec8bd5SPeter Maydell  * @info: handle to the boot info struct
14212ec8bd5SPeter Maydell  * Registers a machine init done notifier that copies to memory
14312ec8bd5SPeter Maydell  * everything needed to boot, depending on machine and user options:
14412ec8bd5SPeter Maydell  * kernel image, boot loaders, initrd, dtb. Also registers the CPU
14512ec8bd5SPeter Maydell  * reset handler.
14612ec8bd5SPeter Maydell  *
14712ec8bd5SPeter Maydell  * In case the machine file supports the platform bus device and its
14812ec8bd5SPeter Maydell  * dynamically instantiable sysbus devices, this function must be called
14912ec8bd5SPeter Maydell  * before sysbus-fdt arm_register_platform_bus_fdt_creator. Indeed the
15012ec8bd5SPeter Maydell  * machine init done notifiers are called in registration reverse order.
15112ec8bd5SPeter Maydell  */
1522744ece8STao Xu void arm_load_kernel(ARMCPU *cpu, MachineState *ms, struct arm_boot_info *info);
15312ec8bd5SPeter Maydell 
15412ec8bd5SPeter Maydell AddressSpace *arm_boot_address_space(ARMCPU *cpu,
15512ec8bd5SPeter Maydell                                      const struct arm_boot_info *info);
15612ec8bd5SPeter Maydell 
15712ec8bd5SPeter Maydell /**
15812ec8bd5SPeter Maydell  * arm_load_dtb() - load a device tree binary image into memory
15912ec8bd5SPeter Maydell  * @addr:       the address to load the image at
16012ec8bd5SPeter Maydell  * @binfo:      struct describing the boot environment
16112ec8bd5SPeter Maydell  * @addr_limit: upper limit of the available memory area at @addr
16212ec8bd5SPeter Maydell  * @as:         address space to load image to
16312ec8bd5SPeter Maydell  *
16412ec8bd5SPeter Maydell  * Load a device tree supplied by the machine or by the user  with the
16512ec8bd5SPeter Maydell  * '-dtb' command line option, and put it at offset @addr in target
16612ec8bd5SPeter Maydell  * memory.
16712ec8bd5SPeter Maydell  *
16812ec8bd5SPeter Maydell  * If @addr_limit contains a meaningful value (i.e., it is strictly greater
16912ec8bd5SPeter Maydell  * than @addr), the device tree is only loaded if its size does not exceed
17012ec8bd5SPeter Maydell  * the limit.
17112ec8bd5SPeter Maydell  *
17212ec8bd5SPeter Maydell  * Returns: the size of the device tree image on success,
17312ec8bd5SPeter Maydell  *          0 if the image size exceeds the limit,
17412ec8bd5SPeter Maydell  *          -1 on errors.
17512ec8bd5SPeter Maydell  *
17612ec8bd5SPeter Maydell  * Note: Must not be called unless have_dtb(binfo) is true.
17712ec8bd5SPeter Maydell  */
17812ec8bd5SPeter Maydell int arm_load_dtb(hwaddr addr, const struct arm_boot_info *binfo,
1792744ece8STao Xu                  hwaddr addr_limit, AddressSpace *as, MachineState *ms);
18012ec8bd5SPeter Maydell 
18112ec8bd5SPeter Maydell /* Write a secure board setup routine with a dummy handler for SMCs */
18212ec8bd5SPeter Maydell void arm_write_secure_board_setup_dummy_smc(ARMCPU *cpu,
18312ec8bd5SPeter Maydell                                             const struct arm_boot_info *info,
18412ec8bd5SPeter Maydell                                             hwaddr mvbar_addr);
18512ec8bd5SPeter Maydell 
186*0fe43f0aSCédric Le Goater typedef enum {
187*0fe43f0aSCédric Le Goater     FIXUP_NONE = 0,     /* do nothing */
188*0fe43f0aSCédric Le Goater     FIXUP_TERMINATOR,   /* end of insns */
189*0fe43f0aSCédric Le Goater     FIXUP_BOARDID,      /* overwrite with board ID number */
190*0fe43f0aSCédric Le Goater     FIXUP_BOARD_SETUP,  /* overwrite with board specific setup code address */
191*0fe43f0aSCédric Le Goater     FIXUP_ARGPTR_LO,    /* overwrite with pointer to kernel args */
192*0fe43f0aSCédric Le Goater     FIXUP_ARGPTR_HI,    /* overwrite with pointer to kernel args (high half) */
193*0fe43f0aSCédric Le Goater     FIXUP_ENTRYPOINT_LO, /* overwrite with kernel entry point */
194*0fe43f0aSCédric Le Goater     FIXUP_ENTRYPOINT_HI, /* overwrite with kernel entry point (high half) */
195*0fe43f0aSCédric Le Goater     FIXUP_GIC_CPU_IF,   /* overwrite with GIC CPU interface address */
196*0fe43f0aSCédric Le Goater     FIXUP_BOOTREG,      /* overwrite with boot register address */
197*0fe43f0aSCédric Le Goater     FIXUP_DSB,          /* overwrite with correct DSB insn for cpu */
198*0fe43f0aSCédric Le Goater     FIXUP_MAX,
199*0fe43f0aSCédric Le Goater } FixupType;
200*0fe43f0aSCédric Le Goater 
201*0fe43f0aSCédric Le Goater typedef struct ARMInsnFixup {
202*0fe43f0aSCédric Le Goater     uint32_t insn;
203*0fe43f0aSCédric Le Goater     FixupType fixup;
204*0fe43f0aSCédric Le Goater } ARMInsnFixup;
205*0fe43f0aSCédric Le Goater 
206*0fe43f0aSCédric Le Goater /**
207*0fe43f0aSCédric Le Goater  * arm_write_bootloader - write a bootloader to guest memory
208*0fe43f0aSCédric Le Goater  * @name: name of the bootloader blob
209*0fe43f0aSCédric Le Goater  * @as: AddressSpace to write the bootloader
210*0fe43f0aSCédric Le Goater  * @addr: guest address to write it
211*0fe43f0aSCédric Le Goater  * @insns: the blob to be loaded
212*0fe43f0aSCédric Le Goater  * @fixupcontext: context to be used for any fixups in @insns
213*0fe43f0aSCédric Le Goater  *
214*0fe43f0aSCédric Le Goater  * Write a bootloader to guest memory at address @addr in the address
215*0fe43f0aSCédric Le Goater  * space @as. @name is the name to use for the resulting ROM blob, so
216*0fe43f0aSCédric Le Goater  * it should be unique in the system and reasonably identifiable for debugging.
217*0fe43f0aSCédric Le Goater  *
218*0fe43f0aSCédric Le Goater  * @insns must be an array of ARMInsnFixup structs, each of which has
219*0fe43f0aSCédric Le Goater  * one 32-bit value to be written to the guest memory, and a fixup to be
220*0fe43f0aSCédric Le Goater  * applied to the value. FIXUP_NONE (do nothing) is value 0, so effectively
221*0fe43f0aSCédric Le Goater  * the fixup is optional when writing a struct initializer.
222*0fe43f0aSCédric Le Goater  * The final entry in the array must be { 0, FIXUP_TERMINATOR }.
223*0fe43f0aSCédric Le Goater  *
224*0fe43f0aSCédric Le Goater  * All other supported fixup types have the semantics "ignore insn
225*0fe43f0aSCédric Le Goater  * and instead use the value from the array element @fixupcontext[fixup]".
226*0fe43f0aSCédric Le Goater  * The caller should therefore provide @fixupcontext as an array of
227*0fe43f0aSCédric Le Goater  * size FIXUP_MAX whose elements have been initialized for at least
228*0fe43f0aSCédric Le Goater  * the entries that @insns refers to.
229*0fe43f0aSCédric Le Goater  */
230*0fe43f0aSCédric Le Goater void arm_write_bootloader(const char *name,
231*0fe43f0aSCédric Le Goater                           AddressSpace *as, hwaddr addr,
232*0fe43f0aSCédric Le Goater                           const ARMInsnFixup *insns,
233*0fe43f0aSCédric Le Goater                           const uint32_t *fixupcontext);
234*0fe43f0aSCédric Le Goater 
23512ec8bd5SPeter Maydell #endif /* HW_ARM_BOOT_H */
236