hw/i386: add device tree support
With "-dtb" on command-line: - append the device tree blob to the kernel image; - pass the blob's pointer to the kernel through setup_data, as requested by upstream kernel commit da6b737b9ab7 ("x86: Add device tree support"). The device tree blob is passed as-is to the guest; none of its fields is modified nor updated. This is not an issue; the kernel commit above uses the device tree only as an extension to the traditional kernel configuration. To: "Michael S. Tsirkin" <mst@redhat.com> To: Paolo Bonzini <pbonzini@redhat.com> To: Richard Henderson <rth@twiddle.net> To: Eduardo Habkost <ehabkost@redhat.com> Cc: qemu-devel@nongnu.org Cc: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com> Message-Id: <1459973054-2777-1-git-send-email-borneo.antonio@gmail.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
fd9a304830
commit
3cbeb52467
46
hw/i386/pc.c
46
hw/i386/pc.c
@ -812,11 +812,26 @@ static long get_file_size(FILE *f)
|
|||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* setup_data types */
|
||||||
|
#define SETUP_NONE 0
|
||||||
|
#define SETUP_E820_EXT 1
|
||||||
|
#define SETUP_DTB 2
|
||||||
|
#define SETUP_PCI 3
|
||||||
|
#define SETUP_EFI 4
|
||||||
|
|
||||||
|
struct setup_data {
|
||||||
|
uint64_t next;
|
||||||
|
uint32_t type;
|
||||||
|
uint32_t len;
|
||||||
|
uint8_t data[0];
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
static void load_linux(PCMachineState *pcms,
|
static void load_linux(PCMachineState *pcms,
|
||||||
FWCfgState *fw_cfg)
|
FWCfgState *fw_cfg)
|
||||||
{
|
{
|
||||||
uint16_t protocol;
|
uint16_t protocol;
|
||||||
int setup_size, kernel_size, initrd_size = 0, cmdline_size;
|
int setup_size, kernel_size, initrd_size = 0, cmdline_size;
|
||||||
|
int dtb_size, setup_data_offset;
|
||||||
uint32_t initrd_max;
|
uint32_t initrd_max;
|
||||||
uint8_t header[8192], *setup, *kernel, *initrd_data;
|
uint8_t header[8192], *setup, *kernel, *initrd_data;
|
||||||
hwaddr real_addr, prot_addr, cmdline_addr, initrd_addr = 0;
|
hwaddr real_addr, prot_addr, cmdline_addr, initrd_addr = 0;
|
||||||
@ -824,8 +839,10 @@ static void load_linux(PCMachineState *pcms,
|
|||||||
char *vmode;
|
char *vmode;
|
||||||
MachineState *machine = MACHINE(pcms);
|
MachineState *machine = MACHINE(pcms);
|
||||||
PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
|
PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
|
||||||
|
struct setup_data *setup_data;
|
||||||
const char *kernel_filename = machine->kernel_filename;
|
const char *kernel_filename = machine->kernel_filename;
|
||||||
const char *initrd_filename = machine->initrd_filename;
|
const char *initrd_filename = machine->initrd_filename;
|
||||||
|
const char *dtb_filename = machine->dtb;
|
||||||
const char *kernel_cmdline = machine->kernel_cmdline;
|
const char *kernel_cmdline = machine->kernel_cmdline;
|
||||||
|
|
||||||
/* Align to 16 bytes as a paranoia measure */
|
/* Align to 16 bytes as a paranoia measure */
|
||||||
@ -988,6 +1005,35 @@ static void load_linux(PCMachineState *pcms,
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
||||||
|
/* append dtb to kernel */
|
||||||
|
if (dtb_filename) {
|
||||||
|
if (protocol < 0x209) {
|
||||||
|
fprintf(stderr, "qemu: Linux kernel too old to load a dtb\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
dtb_size = get_image_size(dtb_filename);
|
||||||
|
if (dtb_size <= 0) {
|
||||||
|
fprintf(stderr, "qemu: error reading dtb %s: %s\n",
|
||||||
|
dtb_filename, strerror(errno));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
setup_data_offset = QEMU_ALIGN_UP(kernel_size, 16);
|
||||||
|
kernel_size = setup_data_offset + sizeof(struct setup_data) + dtb_size;
|
||||||
|
kernel = g_realloc(kernel, kernel_size);
|
||||||
|
|
||||||
|
stq_p(header+0x250, prot_addr + setup_data_offset);
|
||||||
|
|
||||||
|
setup_data = (struct setup_data *)(kernel + setup_data_offset);
|
||||||
|
setup_data->next = 0;
|
||||||
|
setup_data->type = cpu_to_le32(SETUP_DTB);
|
||||||
|
setup_data->len = cpu_to_le32(dtb_size);
|
||||||
|
|
||||||
|
load_image_size(dtb_filename, setup_data->data, dtb_size);
|
||||||
|
}
|
||||||
|
|
||||||
memcpy(setup, header, MIN(sizeof(header), setup_size));
|
memcpy(setup, header, MIN(sizeof(header), setup_size));
|
||||||
|
|
||||||
fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, prot_addr);
|
fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, prot_addr);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user