33
44#include <linux/firmware.h>
55#include <asm/cpu.h>
6+ #include <linux/slab.h>
67#include <asm/microcode_intel.h>
78
89#include "ifs.h"
910
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+
10172static int ifs_sanity_check (struct device * dev ,
11173 const struct microcode_header_intel * mc_header )
12174{
@@ -74,6 +236,7 @@ static bool ifs_image_sanity_check(struct device *dev, const struct microcode_he
74236 */
75237void ifs_load_firmware (struct device * dev )
76238{
239+ struct ifs_data * ifsd = ifs_get_data (dev );
77240 const struct firmware * fw ;
78241 char scan_path [32 ];
79242 int ret ;
@@ -84,11 +247,20 @@ void ifs_load_firmware(struct device *dev)
84247 ret = request_firmware_direct (& fw , scan_path , dev );
85248 if (ret ) {
86249 dev_err (dev , "ifs file %s load failed\n" , scan_path );
87- return ;
250+ goto done ;
88251 }
89252
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 )) {
91254 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 );
92260
261+ ret = scan_chunks_sanity_check (dev );
262+ release :
93263 release_firmware (fw );
264+ done :
265+ ifsd -> loaded = (ret == 0 );
94266}
0 commit comments