18b8da30e94fb82a1e1574bffae2de686ec13fad
[coreboot.git] / src / cpu / amd / microcode / microcode.c
1 /*
2  * This file is part of the coreboot project.
3  *
4  * Copyright (C) 2007 Advanced Micro Devices, Inc.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; version 2 of the License.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
18  */
19
20 #ifndef __ROMCC__
21
22 #include <stdint.h>
23 #include <console/console.h>
24 #include <cpu/cpu.h>
25 #include <cpu/x86/msr.h>
26 #include <cpu/amd/microcode.h>
27 #include <cpu/x86/cache.h>
28
29 #endif
30
31 struct microcode {
32         u32 date_code;
33         u32 patch_id;
34
35         u16 m_patch_data_id;
36         u8 m_patch_data_len;
37         u8 init_flag;
38
39         u32 m_patch_data_cksum;
40
41         u32 nb_dev_id;
42         u32 ht_io_hub_dev_id;
43
44         u16 processor_rev_id;
45         u8 ht_io_hub_rev_id;
46         u8 nb_rev_id;
47
48         u8 bios_api_rev;
49         u8 resv1[3];
50
51         u32 match_reg[8];
52
53         u8 m_patch_data[896];
54         u8 resv2[896];
55
56         u8 x86_code_present;
57         u8 x86_code_entry[191];
58 };
59
60 static int need_apply_patch(struct microcode *m, u32 equivalent_processor_rev_id)
61 {
62
63         if (m->processor_rev_id != equivalent_processor_rev_id) {
64                 printk_debug("microcode: rev id does not match this patch.\n");
65                 printk_debug("microcode: Not updated! Fix microcode_updates[] \n");
66                 return 0;
67         }
68         if (m->nb_dev_id) {
69                   //look at the device id, if not found return;
70                   //if(m->nb_rev_id != installed_nb_rev_id) return 0;
71         }
72
73         if (m->ht_io_hub_dev_id) {
74                   //look at the device id, if not found return;
75                   //if(m->ht_io_hub_rev_id != installed_ht_io_bub_rev_id) return 0;
76         }
77
78         if (m->x86_code_present) {
79                   //if(!x86_code_execute()) return 0;
80         }
81
82         return 1;
83 }
84
85
86 void amd_update_microcode(void *microcode_updates, u32 equivalent_processor_rev_id)
87 {
88         u32 patch_id, new_patch_id;
89         struct microcode *m;
90         char *c;
91         msr_t msr;
92
93         msr = rdmsr(0x8b);
94         patch_id = msr.lo;
95
96         printk_debug("microcode: equivalent rev id  = 0x%04x, current patch id = 0x%08x\n", equivalent_processor_rev_id, patch_id);
97
98         m = microcode_updates;
99
100         for(c = microcode_updates; m->date_code;  m = (struct microcode *)c) {
101
102                 if( need_apply_patch(m, equivalent_processor_rev_id) ) {
103                         //apply patch
104
105                         msr.hi = 0;
106                         msr.lo = (u32)m;
107
108                         wrmsr(0xc0010020, msr);
109
110                         printk_debug("microcode: patch id to apply = 0x%08x\n", m->patch_id);
111
112                         //read the patch_id again
113                         msr = rdmsr(0x8b);
114                         new_patch_id = msr.lo;
115
116                         printk_debug("microcode: updated to patch id = 0x%08x %s\n", new_patch_id , (new_patch_id == m->patch_id)?" success\n":" fail\n" );
117                         break;
118                 }
119                 c += 2048;
120         }
121
122 }