static void generic_loader_reset(void *opaque) { GenericLoaderState *s = GENERIC_LOADER(opaque); if (s->set_pc) { CPUClass *cc = CPU_GET_CLASS(s->cpu); cpu_reset(s->cpu); if (cc) { cc->set_pc(s->cpu, s->addr); } } if (s->data_len) { MemTxAttrs attrs = { .unspecified = 0, .secure = 0, .user = 0, .debug = 0, .requester_id = 0, }; attrs.debug = s->attrs.debug; attrs.secure = s->attrs.secure; attrs.requester_id = s->attrs.requester_id; assert(s->data_len < sizeof(s->data)); address_space_rw(s->cpu->as, s->addr, attrs, (uint8_t *)&s->data, s->data_len, true); } }
static void generic_loader_reset(void *opaque) { GenericLoaderState *s = GENERIC_LOADER(opaque); if (s->set_pc) { CPUClass *cc = CPU_GET_CLASS(s->cpu); cpu_reset(s->cpu); if (cc) { cc->set_pc(s->cpu, s->addr); } } if (s->data_len) { assert(s->data_len < sizeof(s->data)); dma_memory_write(s->cpu->as, s->addr, &s->data, s->data_len); } }
static void generic_loader_realize(DeviceState *dev, Error **errp) { GenericLoaderState *s = GENERIC_LOADER(dev); hwaddr entry; int big_endian; int size = 0; s->set_pc = false; /* Perform some error checking on the user's options */ if (s->data || s->data_len || s->data_be) { /* User is loading memory values */ if (s->file) { error_setg(errp, "Specifying a file is not supported when loading " "memory values"); return; } else if (s->force_raw) { error_setg(errp, "Specifying force-raw is not supported when " "loading memory values"); return; } else if (!s->data_len) { /* We can't check for !data here as a value of 0 is still valid. */ error_setg(errp, "Both data and data-len must be specified"); return; } else if (s->data_len > 8) { error_setg(errp, "data-len cannot be greater then 8 bytes"); return; } } else if (s->file || s->force_raw) { /* User is loading an image */ if (s->data || s->data_len || s->data_be) { error_setg(errp, "data can not be specified when loading an " "image"); return; } /* The user specified a file, only set the PC if they also specified * a CPU to use. */ if (s->cpu_num != CPU_NONE) { s->set_pc = true; } } else if (s->addr) { /* User is setting the PC */ if (s->data || s->data_len || s->data_be) { error_setg(errp, "data can not be specified when setting a " "program counter"); return; } else if (!s->cpu_num) { error_setg(errp, "cpu_num must be specified when setting a " "program counter"); return; } s->set_pc = true; } else { /* Did the user specify anything? */ error_setg(errp, "please include valid arguments"); return; } qemu_register_reset_loader(generic_loader_reset, dev); if (s->cpu_num != CPU_NONE) { s->cpu = qemu_get_cpu(s->cpu_num); if (!s->cpu) { error_setg(errp, "Specified boot CPU#%d is nonexistent", s->cpu_num); return; } } else { s->cpu = first_cpu; } #ifdef TARGET_WORDS_BIGENDIAN big_endian = 1; #else big_endian = 0; #endif if (s->file) { AddressSpace *as = s->cpu ? s->cpu->as : NULL; if (!s->force_raw) { size = load_elf_as(s->file, NULL, NULL, &entry, NULL, NULL, big_endian, 0, 0, 0, as); if (size < 0) { size = load_uimage_as(s->file, &entry, NULL, NULL, NULL, NULL, as); } } if (size < 0 || s->force_raw) { /* Default to the maximum size being the machine's ram size */ size = load_image_targphys_as(s->file, s->addr, ram_size, as); } else { s->addr = entry; } if (size < 0) { error_setg(errp, "Cannot load specified image %s", s->file); return; } } /* Convert the data endiannes */ if (s->data_be) { s->data = cpu_to_be64(s->data); } else { s->data = cpu_to_le64(s->data); } /* Xilinx: If qdev_hotplug is set then the machine has already been * created. This means we are hot-plugging a device. We need to forefully * call the reset function to ensure the operation completes. */ if (qdev_hotplug) { generic_loader_reset(dev); } }
static void generic_loader_realize(DeviceState *dev, Error **errp) { GenericLoaderState *s = GENERIC_LOADER(dev); hwaddr entry; int big_endian; int size = 0; s->set_pc = false; /* Xilinx: This is the old deprecated command line argument. * Print a warning to tell users that it will be removed. */ if (s->cpu_num_dep != CPU_NONE) { fprintf(stderr, "The 'cpu=' command line option has been deprecated " \ "and replaced with 'cpu-num='. Please update your command " \ "line to use 'cpu-num=' as 'cpu=' will be removed after the " \ "2017.4 release.\n"); if (s->cpu_num == CPU_NONE) { s->cpu_num = s->cpu_num_dep; } } /* Perform some error checking on the user's options */ if (s->data || s->data_len || s->data_be) { /* User is loading memory values */ if (s->file) { error_setg(errp, "Specifying a file is not supported when loading " "memory values"); return; } else if (s->force_raw) { error_setg(errp, "Specifying force-raw is not supported when " "loading memory values"); return; } else if (!s->data_len) { /* We can't check for !data here as a value of 0 is still valid. */ error_setg(errp, "Both data and data-len must be specified"); return; } else if (s->data_len > 8) { error_setg(errp, "data-len cannot be greater then 8 bytes"); return; } } else if (s->file || s->force_raw) { /* User is loading an image */ if (s->data || s->data_len || s->data_be) { error_setg(errp, "data can not be specified when loading an " "image"); return; } /* The user specified a file, only set the PC if they also specified * a CPU to use. */ if (s->cpu_num != CPU_NONE) { s->set_pc = true; } } else if (s->addr) { /* User is setting the PC */ if (s->data || s->data_len || s->data_be) { error_setg(errp, "data can not be specified when setting a " "program counter"); return; } else if (!s->cpu_num) { error_setg(errp, "cpu_num must be specified when setting a " "program counter"); return; } s->set_pc = true; } else { /* Did the user specify anything? */ error_setg(errp, "please include valid arguments"); return; } qemu_register_reset(generic_loader_reset, dev); if (s->cpu_num != CPU_NONE) { s->cpu = qemu_get_cpu(s->cpu_num); if (!s->cpu) { error_setg(errp, "Specified boot CPU#%d is nonexistent", s->cpu_num); return; } } else { s->cpu = first_cpu; } #ifdef TARGET_WORDS_BIGENDIAN big_endian = 1; #else big_endian = 0; #endif if (s->file) { AddressSpace *as = s->cpu ? s->cpu->as : NULL; if (!s->force_raw) { size = load_elf_as(s->file, NULL, NULL, &entry, NULL, NULL, big_endian, 0, 0, 0, as); if (size < 0) { size = load_uimage_as(s->file, &entry, NULL, NULL, NULL, NULL, as); } } if (size < 0 || s->force_raw) { /* Default to the maximum size being the machine's ram size */ size = load_image_targphys_as(s->file, s->addr, ram_size, as); } else { s->addr = entry; } if (size < 0) { error_setg(errp, "Cannot load specified image %s", s->file); return; } } /* Convert the data endiannes */ if (s->data_be) { s->data = cpu_to_be64(s->data); } else { s->data = cpu_to_le64(s->data); } }