cpu/intel: Do not rely on CBFS microcode having a terminator

Up until now, a dummy terminator was required for CBFS microcode files.
This was a coreboot only requirement in order to terminate the loop which
searches for updates.

Figure out where the microcode file ends, and exit the loop if we pass the
end of the CBFS without finding any updates.

Change-Id: Ib61247e83ae6b67b27fcd61bd40241d4cd7bd246
Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
Reviewed-on: http://review.coreboot.org/4505
Tested-by: build bot (Jenkins)
Reviewed-by: Vladimir Serbinenko <phcoder@gmail.com>
Reviewed-by: Aaron Durbin <adurbin@google.com>
This commit is contained in:
Alexandru Gagniuc 2013-12-08 16:30:07 -06:00
parent 4c37e58ea5
commit b1ae0303ce
1 changed files with 33 additions and 18 deletions

View File

@ -115,25 +115,27 @@ void intel_microcode_load_unlocked(const void *microcode_patch)
const void *intel_microcode_find(void) const void *intel_microcode_find(void)
{ {
struct cbfs_file *microcode_file;
void *microcode_updates; void *microcode_updates;
u32 eax; u32 eax, microcode_len;
u32 pf, rev, sig; u32 pf, rev, sig, update_size;
unsigned int x86_model, x86_family; unsigned int x86_model, x86_family;
const struct microcode *m; const struct microcode *m;
const char *c;
msr_t msr; msr_t msr;
#ifdef __PRE_RAM__ #ifdef __PRE_RAM__
microcode_updates = walkcbfs((char *) MICROCODE_CBFS_FILE); microcode_file = walkcbfs_head((char *) MICROCODE_CBFS_FILE);
#else #else
microcode_updates = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, microcode_file = cbfs_get_file(CBFS_DEFAULT_MEDIA,
MICROCODE_CBFS_FILE, MICROCODE_CBFS_FILE);
CBFS_TYPE_MICROCODE);
#endif #endif
if (!microcode_updates) if (!microcode_file)
return NULL; return NULL;
microcode_updates = CBFS_SUBHEADER(microcode_file);
microcode_len = ntohl(microcode_file->len);
/* CPUID sets MSR 0x8B iff a microcode update has been loaded. */ /* CPUID sets MSR 0x8B iff a microcode update has been loaded. */
msr.lo = 0; msr.lo = 0;
msr.hi = 0; msr.hi = 0;
@ -158,19 +160,32 @@ const void *intel_microcode_find(void)
sig, pf, rev); sig, pf, rev);
#endif #endif
while (microcode_len >= sizeof(*m)) {
m = microcode_updates; m = microcode_updates;
for(c = microcode_updates; m->hdrver; m = (const struct microcode *)c) { /* Newer microcode updates include a size field, whereas older
* containers set it at 0 and are exactly 2048 bytes long */
if (m->total_size) {
update_size = m->total_size;
} else {
#if !defined(__ROMCC__)
printk(BIOS_WARNING, "Microcode has no valid size field!\n");
#endif
update_size = 2048;
}
/* Checkpoint 1: The microcode update falls within CBFS */
if(update_size > microcode_len) {
#if !defined(__ROMCC__)
printk(BIOS_WARNING, "Microcode header corrupted!\n");
#endif
break;
}
if ((m->sig == sig) && (m->pf & pf)) if ((m->sig == sig) && (m->pf & pf))
return m; return m;
if (m->total_size) { microcode_updates += update_size;
c += m->total_size; microcode_len -= update_size;
} else {
#if !defined(__ROMCC__)
printk(BIOS_WARNING, "Microcode has no valid size field!\n");
#endif
c += 2048;
}
} }
/* ROMCC doesn't like NULL. */ /* ROMCC doesn't like NULL. */