qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

hw/arm/allwinner-h3: add Boot ROM support

A real Allwinner H3 SoC contains a Boot ROM which is the
first code that runs right after the SoC is powered on.
The Boot ROM is responsible for loading user code (e.g. a bootloader)
from any of the supported external devices and writing the downloaded
code to internal SRAM. After loading the SoC begins executing the code
written to SRAM.

This commits adds emulation of the Boot ROM firmware setup functionality
by loading user code from SD card in the A1 SRAM. While the A1 SRAM is
64KiB, we limit the size to 32KiB because the real H3 Boot ROM also rejects
sizes larger than 32KiB. For reference, this behaviour is documented
by the Linux Sunxi project wiki at:

https://linux-sunxi.org/BROM#U-Boot_SPL_limitations

Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Message-id: 20200311221854.30370-11-nieklinnenbank@gmail.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

authored by

Niek Linnenbank and committed by
Peter Maydell
a80beb16 29d08975

+43
+17
hw/arm/allwinner-h3.c
··· 29 29 #include "hw/char/serial.h" 30 30 #include "hw/misc/unimp.h" 31 31 #include "hw/usb/hcd-ehci.h" 32 + #include "hw/loader.h" 32 33 #include "sysemu/sysemu.h" 33 34 #include "hw/arm/allwinner-h3.h" 34 35 ··· 169 170 enum { 170 171 AW_H3_GIC_NUM_SPI = 128 171 172 }; 173 + 174 + void allwinner_h3_bootrom_setup(AwH3State *s, BlockBackend *blk) 175 + { 176 + const int64_t rom_size = 32 * KiB; 177 + g_autofree uint8_t *buffer = g_new0(uint8_t, rom_size); 178 + 179 + if (blk_pread(blk, 8 * KiB, buffer, rom_size) < 0) { 180 + error_setg(&error_fatal, "%s: failed to read BlockBackend data", 181 + __func__); 182 + return; 183 + } 184 + 185 + rom_add_blob("allwinner-h3.bootrom", buffer, rom_size, 186 + rom_size, s->memmap[AW_H3_SRAM_A1], 187 + NULL, NULL, NULL, NULL, false); 188 + } 172 189 173 190 static void allwinner_h3_init(Object *obj) 174 191 {
+5
hw/arm/orangepi.c
··· 97 97 memory_region_add_subregion(get_system_memory(), h3->memmap[AW_H3_SDRAM], 98 98 machine->ram); 99 99 100 + /* Load target kernel or start using BootROM */ 101 + if (!machine->kernel_filename && blk_is_available(blk)) { 102 + /* Use Boot ROM to copy data from SD card to SRAM */ 103 + allwinner_h3_bootrom_setup(h3, blk); 104 + } 100 105 orangepi_binfo.loader_start = h3->memmap[AW_H3_SDRAM]; 101 106 orangepi_binfo.ram_size = machine->ram_size; 102 107 arm_load_kernel(ARM_CPU(first_cpu), machine, &orangepi_binfo);
+21
include/hw/arm/allwinner-h3.h
··· 46 46 #include "hw/sd/allwinner-sdhost.h" 47 47 #include "hw/net/allwinner-sun8i-emac.h" 48 48 #include "target/arm/cpu.h" 49 + #include "sysemu/block-backend.h" 49 50 50 51 /** 51 52 * Allwinner H3 device list ··· 128 129 MemoryRegion sram_a2; 129 130 MemoryRegion sram_c; 130 131 } AwH3State; 132 + 133 + /** 134 + * Emulate Boot ROM firmware setup functionality. 135 + * 136 + * A real Allwinner H3 SoC contains a Boot ROM 137 + * which is the first code that runs right after 138 + * the SoC is powered on. The Boot ROM is responsible 139 + * for loading user code (e.g. a bootloader) from any 140 + * of the supported external devices and writing the 141 + * downloaded code to internal SRAM. After loading the SoC 142 + * begins executing the code written to SRAM. 143 + * 144 + * This function emulates the Boot ROM by copying 32 KiB 145 + * of data from the given block device and writes it to 146 + * the start of the first internal SRAM memory. 147 + * 148 + * @s: Allwinner H3 state object pointer 149 + * @blk: Block backend device object pointer 150 + */ 151 + void allwinner_h3_bootrom_setup(AwH3State *s, BlockBackend *blk); 131 152 132 153 #endif /* HW_ARM_ALLWINNER_H3_H */