Пример #1
0
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;
}