3
3
4
4
#include <linux/firmware.h>
5
5
#include <asm/cpu.h>
6
+ #include <linux/slab.h>
6
7
#include <asm/microcode_intel.h>
7
8
8
9
#include "ifs.h"
9
10
11
+ struct ifs_header {
12
+ u32 header_ver ;
13
+ u32 blob_revision ;
14
+ u32 date ;
15
+ u32 processor_sig ;
16
+ u32 check_sum ;
17
+ u32 loader_rev ;
18
+ u32 processor_flags ;
19
+ u32 metadata_size ;
20
+ u32 total_size ;
21
+ u32 fusa_info ;
22
+ u64 reserved ;
23
+ };
24
+
25
+ #define IFS_HEADER_SIZE (sizeof(struct ifs_header))
26
+ static struct ifs_header * ifs_header_ptr ; /* pointer to the ifs image header */
27
+ static u64 ifs_hash_ptr ; /* Address of ifs metadata (hash) */
28
+ static u64 ifs_test_image_ptr ; /* 256B aligned address of test pattern */
29
+ static DECLARE_COMPLETION (ifs_done );
30
+
31
+ static const char * const scan_hash_status [] = {
32
+ [0 ] = "No error reported" ,
33
+ [1 ] = "Attempt to copy scan hashes when copy already in progress" ,
34
+ [2 ] = "Secure Memory not set up correctly" ,
35
+ [3 ] = "FuSaInfo.ProgramID does not match or ff-mm-ss does not match" ,
36
+ [4 ] = "Reserved" ,
37
+ [5 ] = "Integrity check failed" ,
38
+ [6 ] = "Scan reload or test is in progress"
39
+ };
40
+
41
+ static const char * const scan_authentication_status [] = {
42
+ [0 ] = "No error reported" ,
43
+ [1 ] = "Attempt to authenticate a chunk which is already marked as authentic" ,
44
+ [2 ] = "Chunk authentication error. The hash of chunk did not match expected value"
45
+ };
46
+
47
+ /*
48
+ * To copy scan hashes and authenticate test chunks, the initiating cpu must point
49
+ * to the EDX:EAX to the test image in linear address.
50
+ * Run wrmsr(MSR_COPY_SCAN_HASHES) for scan hash copy and run wrmsr(MSR_AUTHENTICATE_AND_COPY_CHUNK)
51
+ * for scan hash copy and test chunk authentication.
52
+ */
53
+ static void copy_hashes_authenticate_chunks (struct work_struct * work )
54
+ {
55
+ struct ifs_work * local_work = container_of (work , struct ifs_work , w );
56
+ union ifs_scan_hashes_status hashes_status ;
57
+ union ifs_chunks_auth_status chunk_status ;
58
+ struct device * dev = local_work -> dev ;
59
+ int i , num_chunks , chunk_size ;
60
+ struct ifs_data * ifsd ;
61
+ u64 linear_addr , base ;
62
+ u32 err_code ;
63
+
64
+ ifsd = ifs_get_data (dev );
65
+ /* run scan hash copy */
66
+ wrmsrl (MSR_COPY_SCAN_HASHES , ifs_hash_ptr );
67
+ rdmsrl (MSR_SCAN_HASHES_STATUS , hashes_status .data );
68
+
69
+ /* enumerate the scan image information */
70
+ num_chunks = hashes_status .num_chunks ;
71
+ chunk_size = hashes_status .chunk_size * 1024 ;
72
+ err_code = hashes_status .error_code ;
73
+
74
+ if (!hashes_status .valid ) {
75
+ ifsd -> loading_error = true;
76
+ if (err_code >= ARRAY_SIZE (scan_hash_status )) {
77
+ dev_err (dev , "invalid error code 0x%x for hash copy\n" , err_code );
78
+ goto done ;
79
+ }
80
+ dev_err (dev , "Hash copy error : %s" , scan_hash_status [err_code ]);
81
+ goto done ;
82
+ }
83
+
84
+ /* base linear address to the scan data */
85
+ base = ifs_test_image_ptr ;
86
+
87
+ /* scan data authentication and copy chunks to secured memory */
88
+ for (i = 0 ; i < num_chunks ; i ++ ) {
89
+ linear_addr = base + i * chunk_size ;
90
+ linear_addr |= i ;
91
+
92
+ wrmsrl (MSR_AUTHENTICATE_AND_COPY_CHUNK , linear_addr );
93
+ rdmsrl (MSR_CHUNKS_AUTHENTICATION_STATUS , chunk_status .data );
94
+
95
+ ifsd -> valid_chunks = chunk_status .valid_chunks ;
96
+ err_code = chunk_status .error_code ;
97
+
98
+ if (err_code ) {
99
+ ifsd -> loading_error = true;
100
+ if (err_code >= ARRAY_SIZE (scan_authentication_status )) {
101
+ dev_err (dev ,
102
+ "invalid error code 0x%x for authentication\n" , err_code );
103
+ goto done ;
104
+ }
105
+ dev_err (dev , "Chunk authentication error %s\n" ,
106
+ scan_authentication_status [err_code ]);
107
+ goto done ;
108
+ }
109
+ }
110
+ done :
111
+ complete (& ifs_done );
112
+ }
113
+
114
+ /*
115
+ * IFS requires scan chunks authenticated per each socket in the platform.
116
+ * Once the test chunk is authenticated, it is automatically copied to secured memory
117
+ * and proceed the authentication for the next chunk.
118
+ */
119
+ static int scan_chunks_sanity_check (struct device * dev )
120
+ {
121
+ int metadata_size , curr_pkg , cpu , ret = - ENOMEM ;
122
+ struct ifs_data * ifsd = ifs_get_data (dev );
123
+ bool * package_authenticated ;
124
+ struct ifs_work local_work ;
125
+ char * test_ptr ;
126
+
127
+ package_authenticated = kcalloc (topology_max_packages (), sizeof (bool ), GFP_KERNEL );
128
+ if (!package_authenticated )
129
+ return ret ;
130
+
131
+ metadata_size = ifs_header_ptr -> metadata_size ;
132
+
133
+ /* Spec says that if the Meta Data Size = 0 then it should be treated as 2000 */
134
+ if (metadata_size == 0 )
135
+ metadata_size = 2000 ;
136
+
137
+ /* Scan chunk start must be 256 byte aligned */
138
+ if ((metadata_size + IFS_HEADER_SIZE ) % 256 ) {
139
+ dev_err (dev , "Scan pattern offset within the binary is not 256 byte aligned\n" );
140
+ return - EINVAL ;
141
+ }
142
+
143
+ test_ptr = (char * )ifs_header_ptr + IFS_HEADER_SIZE + metadata_size ;
144
+ ifsd -> loading_error = false;
145
+
146
+ ifs_test_image_ptr = (u64 )test_ptr ;
147
+ ifsd -> loaded_version = ifs_header_ptr -> blob_revision ;
148
+
149
+ /* copy the scan hash and authenticate per package */
150
+ cpus_read_lock ();
151
+ for_each_online_cpu (cpu ) {
152
+ curr_pkg = topology_physical_package_id (cpu );
153
+ if (package_authenticated [curr_pkg ])
154
+ continue ;
155
+ reinit_completion (& ifs_done );
156
+ local_work .dev = dev ;
157
+ INIT_WORK (& local_work .w , copy_hashes_authenticate_chunks );
158
+ schedule_work_on (cpu , & local_work .w );
159
+ wait_for_completion (& ifs_done );
160
+ if (ifsd -> loading_error )
161
+ goto out ;
162
+ package_authenticated [curr_pkg ] = 1 ;
163
+ }
164
+ ret = 0 ;
165
+ out :
166
+ cpus_read_unlock ();
167
+ kfree (package_authenticated );
168
+
169
+ return ret ;
170
+ }
171
+
10
172
static int ifs_sanity_check (struct device * dev ,
11
173
const struct microcode_header_intel * mc_header )
12
174
{
@@ -74,6 +236,7 @@ static bool ifs_image_sanity_check(struct device *dev, const struct microcode_he
74
236
*/
75
237
void ifs_load_firmware (struct device * dev )
76
238
{
239
+ struct ifs_data * ifsd = ifs_get_data (dev );
77
240
const struct firmware * fw ;
78
241
char scan_path [32 ];
79
242
int ret ;
@@ -84,11 +247,20 @@ void ifs_load_firmware(struct device *dev)
84
247
ret = request_firmware_direct (& fw , scan_path , dev );
85
248
if (ret ) {
86
249
dev_err (dev , "ifs file %s load failed\n" , scan_path );
87
- return ;
250
+ goto done ;
88
251
}
89
252
90
- if (!ifs_image_sanity_check (dev , (struct microcode_header_intel * )fw -> data ))
253
+ if (!ifs_image_sanity_check (dev , (struct microcode_header_intel * )fw -> data )) {
91
254
dev_err (dev , "ifs header sanity check failed\n" );
255
+ goto release ;
256
+ }
257
+
258
+ ifs_header_ptr = (struct ifs_header * )fw -> data ;
259
+ ifs_hash_ptr = (u64 )(ifs_header_ptr + 1 );
92
260
261
+ ret = scan_chunks_sanity_check (dev );
262
+ release :
93
263
release_firmware (fw );
264
+ done :
265
+ ifsd -> loaded = (ret == 0 );
94
266
}
0 commit comments