m68k: write bootinfo as rom section and re-randomize on reboot

Rather than poking directly into RAM, add the bootinfo block as a proper
ROM, so that it's restored when rebooting the system. This way, if the
guest corrupts any of the bootinfo items, but then tries to reboot,
it'll still be restored back to normal as expected.

Then, since the RNG seed needs to be fresh on each boot, regenerate the
RNG seed in the ROM when reseting the CPU.

Cc: Geert Uytterhoeven <geert@linux-m68k.org>
Cc: Laurent Vivier <laurent@vivier.eu>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Message-Id: <20221023191340.36238-1-Jason@zx2c4.com>
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
This commit is contained in:
Jason A. Donenfeld 2022-10-23 21:13:41 +02:00 committed by Laurent Vivier
parent 693869a66e
commit 281ac13ece
3 changed files with 110 additions and 58 deletions

View file

@ -321,11 +321,22 @@ static const TypeInfo glue_info = {
},
};
typedef struct {
M68kCPU *cpu;
struct bi_record *rng_seed;
} ResetInfo;
static void main_cpu_reset(void *opaque)
{
M68kCPU *cpu = opaque;
ResetInfo *reset_info = opaque;
M68kCPU *cpu = reset_info->cpu;
CPUState *cs = CPU(cpu);
if (reset_info->rng_seed) {
qemu_guest_getrandom_nofail((void *)reset_info->rng_seed->data + 2,
be16_to_cpu(*(uint16_t *)reset_info->rng_seed->data));
}
cpu_reset(cs);
cpu->env.aregs[7] = ldl_phys(cs->as, 0);
cpu->env.pc = ldl_phys(cs->as, 4);
@ -386,6 +397,7 @@ static void q800_init(MachineState *machine)
NubusBus *nubus;
DeviceState *glue;
DriveInfo *dinfo;
ResetInfo *reset_info;
uint8_t rng_seed[32];
linux_boot = (kernel_filename != NULL);
@ -396,9 +408,12 @@ static void q800_init(MachineState *machine)
exit(1);
}
reset_info = g_new0(ResetInfo, 1);
/* init CPUs */
cpu = M68K_CPU(cpu_create(machine->cpu_type));
qemu_register_reset(main_cpu_reset, cpu);
reset_info->cpu = cpu;
qemu_register_reset(main_cpu_reset, reset_info);
/* RAM */
memory_region_add_subregion(get_system_memory(), 0, machine->ram);
@ -598,6 +613,14 @@ static void q800_init(MachineState *machine)
cs = CPU(cpu);
if (linux_boot) {
uint64_t high;
void *param_blob, *param_ptr, *param_rng_seed;
if (kernel_cmdline) {
param_blob = g_malloc(strlen(kernel_cmdline) + 1024);
} else {
param_blob = g_malloc(1024);
}
kernel_size = load_elf(kernel_filename, NULL, NULL, NULL,
&elf_entry, NULL, &high, NULL, 1,
EM_68K, 0, 0);
@ -607,23 +630,24 @@ static void q800_init(MachineState *machine)
}
stl_phys(cs->as, 4, elf_entry); /* reset initial PC */
parameters_base = (high + 1) & ~1;
param_ptr = param_blob;
BOOTINFO1(cs->as, parameters_base, BI_MACHTYPE, MACH_MAC);
BOOTINFO1(cs->as, parameters_base, BI_FPUTYPE, FPU_68040);
BOOTINFO1(cs->as, parameters_base, BI_MMUTYPE, MMU_68040);
BOOTINFO1(cs->as, parameters_base, BI_CPUTYPE, CPU_68040);
BOOTINFO1(cs->as, parameters_base, BI_MAC_CPUID, CPUB_68040);
BOOTINFO1(cs->as, parameters_base, BI_MAC_MODEL, MAC_MODEL_Q800);
BOOTINFO1(cs->as, parameters_base,
BOOTINFO1(param_ptr, BI_MACHTYPE, MACH_MAC);
BOOTINFO1(param_ptr, BI_FPUTYPE, FPU_68040);
BOOTINFO1(param_ptr, BI_MMUTYPE, MMU_68040);
BOOTINFO1(param_ptr, BI_CPUTYPE, CPU_68040);
BOOTINFO1(param_ptr, BI_MAC_CPUID, CPUB_68040);
BOOTINFO1(param_ptr, BI_MAC_MODEL, MAC_MODEL_Q800);
BOOTINFO1(param_ptr,
BI_MAC_MEMSIZE, ram_size >> 20); /* in MB */
BOOTINFO2(cs->as, parameters_base, BI_MEMCHUNK, 0, ram_size);
BOOTINFO1(cs->as, parameters_base, BI_MAC_VADDR,
BOOTINFO2(param_ptr, BI_MEMCHUNK, 0, ram_size);
BOOTINFO1(param_ptr, BI_MAC_VADDR,
VIDEO_BASE + macfb_mode->offset);
BOOTINFO1(cs->as, parameters_base, BI_MAC_VDEPTH, graphic_depth);
BOOTINFO1(cs->as, parameters_base, BI_MAC_VDIM,
BOOTINFO1(param_ptr, BI_MAC_VDEPTH, graphic_depth);
BOOTINFO1(param_ptr, BI_MAC_VDIM,
(graphic_height << 16) | graphic_width);
BOOTINFO1(cs->as, parameters_base, BI_MAC_VROW, macfb_mode->stride);
BOOTINFO1(cs->as, parameters_base, BI_MAC_SCCBASE, SCC_BASE);
BOOTINFO1(param_ptr, BI_MAC_VROW, macfb_mode->stride);
BOOTINFO1(param_ptr, BI_MAC_SCCBASE, SCC_BASE);
rom = g_malloc(sizeof(*rom));
memory_region_init_ram_ptr(rom, NULL, "m68k_fake_mac.rom",
@ -632,13 +656,14 @@ static void q800_init(MachineState *machine)
memory_region_add_subregion(get_system_memory(), MACROM_ADDR, rom);
if (kernel_cmdline) {
BOOTINFOSTR(cs->as, parameters_base, BI_COMMAND_LINE,
BOOTINFOSTR(param_ptr, BI_COMMAND_LINE,
kernel_cmdline);
}
/* Pass seed to RNG. */
param_rng_seed = param_ptr;
qemu_guest_getrandom_nofail(rng_seed, sizeof(rng_seed));
BOOTINFODATA(cs->as, parameters_base, BI_RNG_SEED,
BOOTINFODATA(param_ptr, BI_RNG_SEED,
rng_seed, sizeof(rng_seed));
/* load initrd */
@ -653,13 +678,19 @@ static void q800_init(MachineState *machine)
initrd_base = (ram_size - initrd_size) & TARGET_PAGE_MASK;
load_image_targphys(initrd_filename, initrd_base,
ram_size - initrd_base);
BOOTINFO2(cs->as, parameters_base, BI_RAMDISK, initrd_base,
BOOTINFO2(param_ptr, BI_RAMDISK, initrd_base,
initrd_size);
} else {
initrd_base = 0;
initrd_size = 0;
}
BOOTINFO0(cs->as, parameters_base, BI_LAST);
BOOTINFO0(param_ptr, BI_LAST);
rom_add_blob_fixed_as("bootinfo", param_blob, param_ptr - param_blob,
parameters_base, cs->as);
reset_info->rng_seed = rom_ptr_for_as(cs->as, parameters_base,
param_ptr - param_blob) +
(param_rng_seed - param_blob);
g_free(param_blob);
} else {
uint8_t *ptr;
/* allocate and load BIOS */