Skip to content

Commit 5c7c413

Browse files
bp3tk0vgregkh
authored andcommitted
x86/microcode/AMD: Select which microcode patch to load
Commit 8d171045069c804e5ffaa18be590c42c6af0cf3f upstream. All microcode patches up to the proper BIOS Entrysign fix are loaded only after the sha256 signature carried in the driver has been verified. Microcode patches after the Entrysign fix has been applied, do not need that signature verification anymore. In order to not abandon machines which haven't received the BIOS update yet, add the capability to select which microcode patch to load. The corresponding microcode container supplied through firmware-linux has been modified to carry two patches per CPU type (family/model/stepping) so that the proper one gets selected. Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de> Tested-by: Waiman Long <longman@redhat.com> Link: https://patch.msgid.link/20251027133818.4363-1-bp@kernel.org Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 90c4cb1 commit 5c7c413

1 file changed

Lines changed: 67 additions & 37 deletions

File tree

  • arch/x86/kernel/cpu/microcode

arch/x86/kernel/cpu/microcode/amd.c

Lines changed: 67 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -176,50 +176,61 @@ static u32 cpuid_to_ucode_rev(unsigned int val)
176176
return p.ucode_rev;
177177
}
178178

179+
static u32 get_cutoff_revision(u32 rev)
180+
{
181+
switch (rev >> 8) {
182+
case 0x80012: return 0x8001277; break;
183+
case 0x80082: return 0x800820f; break;
184+
case 0x83010: return 0x830107c; break;
185+
case 0x86001: return 0x860010e; break;
186+
case 0x86081: return 0x8608108; break;
187+
case 0x87010: return 0x8701034; break;
188+
case 0x8a000: return 0x8a0000a; break;
189+
case 0xa0010: return 0xa00107a; break;
190+
case 0xa0011: return 0xa0011da; break;
191+
case 0xa0012: return 0xa001243; break;
192+
case 0xa0082: return 0xa00820e; break;
193+
case 0xa1011: return 0xa101153; break;
194+
case 0xa1012: return 0xa10124e; break;
195+
case 0xa1081: return 0xa108109; break;
196+
case 0xa2010: return 0xa20102f; break;
197+
case 0xa2012: return 0xa201212; break;
198+
case 0xa4041: return 0xa404109; break;
199+
case 0xa5000: return 0xa500013; break;
200+
case 0xa6012: return 0xa60120a; break;
201+
case 0xa7041: return 0xa704109; break;
202+
case 0xa7052: return 0xa705208; break;
203+
case 0xa7080: return 0xa708009; break;
204+
case 0xa70c0: return 0xa70C009; break;
205+
case 0xaa001: return 0xaa00116; break;
206+
case 0xaa002: return 0xaa00218; break;
207+
case 0xb0021: return 0xb002146; break;
208+
case 0xb0081: return 0xb008111; break;
209+
case 0xb1010: return 0xb101046; break;
210+
case 0xb2040: return 0xb204031; break;
211+
case 0xb4040: return 0xb404031; break;
212+
case 0xb4041: return 0xb404101; break;
213+
case 0xb6000: return 0xb600031; break;
214+
case 0xb6080: return 0xb608031; break;
215+
case 0xb7000: return 0xb700031; break;
216+
default: break;
217+
218+
}
219+
return 0;
220+
}
221+
179222
static bool need_sha_check(u32 cur_rev)
180223
{
224+
u32 cutoff;
225+
181226
if (!cur_rev) {
182227
cur_rev = cpuid_to_ucode_rev(bsp_cpuid_1_eax);
183228
pr_info_once("No current revision, generating the lowest one: 0x%x\n", cur_rev);
184229
}
185230

186-
switch (cur_rev >> 8) {
187-
case 0x80012: return cur_rev <= 0x8001277; break;
188-
case 0x80082: return cur_rev <= 0x800820f; break;
189-
case 0x83010: return cur_rev <= 0x830107c; break;
190-
case 0x86001: return cur_rev <= 0x860010e; break;
191-
case 0x86081: return cur_rev <= 0x8608108; break;
192-
case 0x87010: return cur_rev <= 0x8701034; break;
193-
case 0x8a000: return cur_rev <= 0x8a0000a; break;
194-
case 0xa0010: return cur_rev <= 0xa00107a; break;
195-
case 0xa0011: return cur_rev <= 0xa0011da; break;
196-
case 0xa0012: return cur_rev <= 0xa001243; break;
197-
case 0xa0082: return cur_rev <= 0xa00820e; break;
198-
case 0xa1011: return cur_rev <= 0xa101153; break;
199-
case 0xa1012: return cur_rev <= 0xa10124e; break;
200-
case 0xa1081: return cur_rev <= 0xa108109; break;
201-
case 0xa2010: return cur_rev <= 0xa20102f; break;
202-
case 0xa2012: return cur_rev <= 0xa201212; break;
203-
case 0xa4041: return cur_rev <= 0xa404109; break;
204-
case 0xa5000: return cur_rev <= 0xa500013; break;
205-
case 0xa6012: return cur_rev <= 0xa60120a; break;
206-
case 0xa7041: return cur_rev <= 0xa704109; break;
207-
case 0xa7052: return cur_rev <= 0xa705208; break;
208-
case 0xa7080: return cur_rev <= 0xa708009; break;
209-
case 0xa70c0: return cur_rev <= 0xa70C009; break;
210-
case 0xaa001: return cur_rev <= 0xaa00116; break;
211-
case 0xaa002: return cur_rev <= 0xaa00218; break;
212-
case 0xb0021: return cur_rev <= 0xb002146; break;
213-
case 0xb0081: return cur_rev <= 0xb008111; break;
214-
case 0xb1010: return cur_rev <= 0xb101046; break;
215-
case 0xb2040: return cur_rev <= 0xb204031; break;
216-
case 0xb4040: return cur_rev <= 0xb404031; break;
217-
case 0xb4041: return cur_rev <= 0xb404101; break;
218-
case 0xb6000: return cur_rev <= 0xb600031; break;
219-
case 0xb6080: return cur_rev <= 0xb608031; break;
220-
case 0xb7000: return cur_rev <= 0xb700031; break;
221-
default: break;
222-
}
231+
cutoff = get_cutoff_revision(cur_rev);
232+
if (cutoff)
233+
return cur_rev <= cutoff;
223234

224235
pr_info("You should not be seeing this. Please send the following couple of lines to x86-<at>-kernel.org\n");
225236
pr_info("CPUID(1).EAX: 0x%x, current revision: 0x%x\n", bsp_cpuid_1_eax, cur_rev);
@@ -473,6 +484,7 @@ static int verify_patch(const u8 *buf, size_t buf_size, u32 *patch_size)
473484
{
474485
u8 family = x86_family(bsp_cpuid_1_eax);
475486
struct microcode_header_amd *mc_hdr;
487+
u32 cur_rev, cutoff, patch_rev;
476488
u32 sh_psize;
477489
u16 proc_id;
478490
u8 patch_fam;
@@ -514,6 +526,24 @@ static int verify_patch(const u8 *buf, size_t buf_size, u32 *patch_size)
514526
if (patch_fam != family)
515527
return 1;
516528

529+
cur_rev = get_patch_level();
530+
531+
/* No cutoff revision means old/unaffected by signing algorithm weakness => matches */
532+
cutoff = get_cutoff_revision(cur_rev);
533+
if (!cutoff)
534+
goto ok;
535+
536+
patch_rev = mc_hdr->patch_id;
537+
538+
if (cur_rev <= cutoff && patch_rev <= cutoff)
539+
goto ok;
540+
541+
if (cur_rev > cutoff && patch_rev > cutoff)
542+
goto ok;
543+
544+
return 1;
545+
ok:
546+
517547
return 0;
518548
}
519549

0 commit comments

Comments
 (0)