void fw_cfg_add_file_callback(FWCfgState *s, const char *filename, FWCfgCallback select_cb, FWCfgWriteCallback write_cb, void *callback_opaque, void *data, size_t len, bool read_only) { int i, index, count; size_t dsize; MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine()); int order = 0; if (!s->files) { dsize = sizeof(uint32_t) + sizeof(FWCfgFile) * fw_cfg_file_slots(s); s->files = g_malloc0(dsize); fw_cfg_add_bytes(s, FW_CFG_FILE_DIR, s->files, dsize); } count = be32_to_cpu(s->files->count); assert(count < fw_cfg_file_slots(s)); /* Find the insertion point. */ if (mc->legacy_fw_cfg_order) { /* * Sort by order. For files with the same order, we keep them * in the sequence in which they were added. */ order = get_fw_cfg_order(s, filename); for (index = count; index > 0 && order < s->entry_order[index - 1]; index--); } else { /* Sort by file name. */ for (index = count; index > 0 && strcmp(filename, s->files->f[index - 1].name) < 0; index--); } /* * Move all the entries from the index point and after down one * to create a slot for the new entry. Because calculations are * being done with the index, make it so that "i" is the current * index and "i - 1" is the one being copied from, thus the * unusual start and end in the for statement. */ for (i = count + 1; i > index; i--) { s->files->f[i] = s->files->f[i - 1]; s->files->f[i].select = cpu_to_be16(FW_CFG_FILE_FIRST + i); s->entries[0][FW_CFG_FILE_FIRST + i] = s->entries[0][FW_CFG_FILE_FIRST + i - 1]; s->entry_order[i] = s->entry_order[i - 1]; } memset(&s->files->f[index], 0, sizeof(FWCfgFile)); memset(&s->entries[0][FW_CFG_FILE_FIRST + index], 0, sizeof(FWCfgEntry)); pstrcpy(s->files->f[index].name, sizeof(s->files->f[index].name), filename); for (i = 0; i <= count; i++) { if (i != index && strcmp(s->files->f[index].name, s->files->f[i].name) == 0) { error_report("duplicate fw_cfg file name: %s", s->files->f[index].name); exit(1); } } fw_cfg_add_bytes_callback(s, FW_CFG_FILE_FIRST + index, select_cb, write_cb, callback_opaque, data, len, read_only); s->files->f[index].size = cpu_to_be32(len); s->files->f[index].select = cpu_to_be16(FW_CFG_FILE_FIRST + index); s->entry_order[index] = order; trace_fw_cfg_add_file(s, index, s->files->f[index].name, len); s->files->count = cpu_to_be32(count+1); }