static enum ucode_state generic_load_microcode(int cpu, const u8 *data, size_t size) { struct ucode_cpu_info *uci = ucode_cpu_info + cpu; const u8 *ucode_ptr = data; void *new_mc = NULL; void *mc; int new_rev = uci->cpu_sig.rev; unsigned int leftover; unsigned long offset; enum ucode_state state = UCODE_OK; offset = install_equiv_cpu_table(ucode_ptr); if (!offset) { printk(KERN_ERR "microcode: failed to create " "equivalent cpu table\n"); return UCODE_ERROR; } ucode_ptr += offset; leftover = size - offset; while (leftover) { unsigned int uninitialized_var(mc_size); struct microcode_header_amd *mc_header; mc = get_next_ucode(cpu, ucode_ptr, leftover, &mc_size); if (!mc) break; mc_header = (struct microcode_header_amd *)mc; if (get_matching_microcode(cpu, mc, new_rev)) { vfree(new_mc); new_rev = mc_header->patch_id; new_mc = mc; } else vfree(mc); ucode_ptr += mc_size; leftover -= mc_size; } if (new_mc) { if (!leftover) { vfree(uci->mc); uci->mc = new_mc; pr_debug("microcode: CPU%d found a matching microcode " "update with version 0x%x (current=0x%x)\n", cpu, new_rev, uci->cpu_sig.rev); } else { vfree(new_mc); state = UCODE_ERROR; } } else state = UCODE_NFOUND; free_equiv_cpu_table(); return state; }
static enum ucode_state generic_load_microcode(int cpu, const u8 *data, size_t size) { struct ucode_cpu_info *uci = ucode_cpu_info + cpu; struct microcode_header_amd *mc_hdr = NULL; unsigned int mc_size, leftover; int offset; const u8 *ucode_ptr = data; void *new_mc = NULL; unsigned int new_rev = uci->cpu_sig.rev; enum ucode_state state = UCODE_OK; offset = install_equiv_cpu_table(ucode_ptr); if (offset < 0) { pr_err("failed to create equivalent cpu table\n"); return UCODE_ERROR; } ucode_ptr += offset; leftover = size - offset; while (leftover) { mc_hdr = get_next_ucode(cpu, ucode_ptr, leftover, &mc_size); if (!mc_hdr) break; if (get_matching_microcode(cpu, mc_hdr, new_rev)) { vfree(new_mc); new_rev = mc_hdr->patch_id; new_mc = mc_hdr; } else vfree(mc_hdr); ucode_ptr += mc_size; leftover -= mc_size; } if (!new_mc) { state = UCODE_NFOUND; goto free_table; } if (!leftover) { vfree(uci->mc); uci->mc = new_mc; pr_debug("CPU%d update ucode (0x%08x -> 0x%08x)\n", cpu, uci->cpu_sig.rev, new_rev); } else { vfree(new_mc); state = UCODE_ERROR; } free_table: free_equiv_cpu_table(); return state; }