Commit 8ea09c6284 for qemu.org
commit 8ea09c6284c842f0d281651df623b94809ae0349
Author: Bibo Mao <maobibo@loongson.cn>
Date: Fri Aug 7 15:00:28 2026 +0800
hw/loongarch/boot: Check memory boundary in init_boot_rom()
When booting the Linux kernel without UEFI BIOS, QEMU needs to set the boot
param for kernel. For the LoongArch Linux kernel, it is put in structure
loongarch_boot_info, and the total size is 1MB.
Here add memory boundary checking with preparing kernel boot param in
loongarch_boot_info.
Signed-off-by: Bibo Mao <maobibo@loongson.cn>
Reviewed-by: Song Gao <gaosong@loongson.cn>
Message-ID: <20260807070029.1171348-2-maobibo@loongson.cn>
Signed-off-by: Song Gao <gaosong@loongson.cn>
diff --git a/hw/loongarch/boot.c b/hw/loongarch/boot.c
index ef8eae237c..fe91ab16bd 100644
--- a/hw/loongarch/boot.c
+++ b/hw/loongarch/boot.c
@@ -173,12 +173,19 @@ static void init_efi_fdt_table(struct efi_system_table *systab)
systab->nr_tables = 3;
}
-static void init_systab(MachineState *ms,
+static void init_systab(MachineState *ms, size_t size,
struct loongarch_boot_info *info, void *p, void *start)
{
void *bp_tables_start;
struct efi_system_table *systab = p;
LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(ms);
+ size_t len;
+
+ len = ROUND_UP(sizeof(struct efi_system_table), 64 * KiB);
+ if (len > size) {
+ error_report("could not init efi_system_table");
+ exit(1);
+ }
info->a2 = p - start;
@@ -190,29 +197,56 @@ static void init_systab(MachineState *ms,
systab->boottime = 0;
systab->nr_tables = 0;
- p += ROUND_UP(sizeof(struct efi_system_table), 64 * KiB);
+ p += len;
+ size -= len;
systab->tables = p;
bp_tables_start = p;
+ len = ROUND_UP(sizeof(struct efi_boot_memmap) +
+ sizeof(efi_memory_desc_t) * lvms->memmap_entries, 64 * KiB);
+ if (len > size) {
+ error_report("could not init efi_boot_memmap");
+ exit(1);
+ }
+
init_efi_boot_memmap(ms, systab, p, start);
- p += ROUND_UP(sizeof(struct efi_boot_memmap) +
- sizeof(efi_memory_desc_t) * lvms->memmap_entries, 64 * KiB);
+ p += len;
+ size -= len;
+
+ len = ROUND_UP(sizeof(struct efi_initrd), 64 * KiB);
+ if (len > size) {
+ error_report("could not init efi_initrd");
+ exit(1);
+ }
+
init_efi_initrd_table(info, systab, p, start);
- p += ROUND_UP(sizeof(struct efi_initrd), 64 * KiB);
+ p += len;
+ size -= len;
init_efi_fdt_table(systab);
systab->tables = (struct efi_configuration_table *)(bp_tables_start - start);
}
-static void init_cmdline(struct loongarch_boot_info *info, void *p, void *start)
+static size_t init_cmdline(struct loongarch_boot_info *info, void *p,
+ void *start, size_t size)
{
hwaddr cmdline_addr = p - start;
+ size_t len;
info->a0 = 1;
info->a1 = cmdline_addr;
- g_strlcpy(p, info->kernel_cmdline, COMMAND_LINE_SIZE);
+ len = g_strlcpy(p, info->kernel_cmdline, size);
+
+ /* include terminating null byte */
+ if (len < size) {
+ len += 1;
+ } else {
+ len = size;
+ }
+
+ return len;
}
static uint64_t cpu_loongarch_virt_to_phys(void *opaque, uint64_t addr)
@@ -385,15 +419,21 @@ static void loongarch_firmware_boot(LoongArchVirtMachineState *lvms,
fw_cfg_add_kernel_info(info, lvms->fw_cfg);
}
-static void init_boot_rom(MachineState *ms,
+static void init_boot_rom(MachineState *ms, size_t size,
struct loongarch_boot_info *info, void *p)
{
void *start = p;
+ size_t len;
- init_cmdline(info, p, start);
- p += COMMAND_LINE_SIZE;
+ len = init_cmdline(info, p, start, size);
+ len = ROUND_UP(len, 64 * KiB);
+ if (len > size) {
+ error_report("could not init systab");
+ exit(1);
+ }
- init_systab(ms, info, p, start);
+ p += len;
+ init_systab(ms, size - len, info, p, start);
}
static void loongarch_direct_kernel_boot(MachineState *ms,
@@ -403,6 +443,7 @@ static void loongarch_direct_kernel_boot(MachineState *ms,
void *p, *bp;
int64_t kernel_addr = VIRT_FLASH0_BASE;
uint64_t *data;
+ size_t size;
if (info->kernel_filename) {
kernel_addr = load_kernel_info(info, phys_addr_mask);
@@ -415,8 +456,9 @@ static void loongarch_direct_kernel_boot(MachineState *ms,
/* Load cmdline and system tables at [0 - 1 MiB] */
p = g_malloc0(1 * MiB);
bp = p;
- init_boot_rom(ms, info, p);
- rom_add_blob_fixed_as("boot_info", bp, 1 * MiB, 0, &address_space_memory);
+ size = 1 * MiB;
+ init_boot_rom(ms, size, info, p);
+ rom_add_blob_fixed_as("boot_info", bp, size, 0, &address_space_memory);
/* Load slave boot code at pflash0 . */
void *boot_code = g_malloc0(VIRT_FLASH0_SIZE);