diff options
Diffstat (limited to 'drivers/char/tpm/tpm_bios.c')
-rw-r--r-- | drivers/char/tpm/tpm_bios.c | 137 |
1 files changed, 67 insertions, 70 deletions
diff --git a/drivers/char/tpm/tpm_bios.c b/drivers/char/tpm/tpm_bios.c index 537aa45d8c67..a611972024e6 100644 --- a/drivers/char/tpm/tpm_bios.c +++ b/drivers/char/tpm/tpm_bios.c | |||
@@ -29,6 +29,11 @@ | |||
29 | #define MAX_TEXT_EVENT 1000 /* Max event string length */ | 29 | #define MAX_TEXT_EVENT 1000 /* Max event string length */ |
30 | #define ACPI_TCPA_SIG "TCPA" /* 0x41504354 /'TCPA' */ | 30 | #define ACPI_TCPA_SIG "TCPA" /* 0x41504354 /'TCPA' */ |
31 | 31 | ||
32 | enum bios_platform_class { | ||
33 | BIOS_CLIENT = 0x00, | ||
34 | BIOS_SERVER = 0x01, | ||
35 | }; | ||
36 | |||
32 | struct tpm_bios_log { | 37 | struct tpm_bios_log { |
33 | void *bios_event_log; | 38 | void *bios_event_log; |
34 | void *bios_event_log_end; | 39 | void *bios_event_log_end; |
@@ -36,9 +41,18 @@ struct tpm_bios_log { | |||
36 | 41 | ||
37 | struct acpi_tcpa { | 42 | struct acpi_tcpa { |
38 | struct acpi_table_header hdr; | 43 | struct acpi_table_header hdr; |
39 | u16 reserved; | 44 | u16 platform_class; |
40 | u32 log_max_len __attribute__ ((packed)); | 45 | union { |
41 | u32 log_start_addr __attribute__ ((packed)); | 46 | struct client_hdr { |
47 | u32 log_max_len __attribute__ ((packed)); | ||
48 | u64 log_start_addr __attribute__ ((packed)); | ||
49 | } client; | ||
50 | struct server_hdr { | ||
51 | u16 reserved; | ||
52 | u64 log_max_len __attribute__ ((packed)); | ||
53 | u64 log_start_addr __attribute__ ((packed)); | ||
54 | } server; | ||
55 | }; | ||
42 | }; | 56 | }; |
43 | 57 | ||
44 | struct tcpa_event { | 58 | struct tcpa_event { |
@@ -91,6 +105,12 @@ static const char* tcpa_event_type_strings[] = { | |||
91 | "Non-Host Info" | 105 | "Non-Host Info" |
92 | }; | 106 | }; |
93 | 107 | ||
108 | struct tcpa_pc_event { | ||
109 | u32 event_id; | ||
110 | u32 event_size; | ||
111 | u8 event_data[0]; | ||
112 | }; | ||
113 | |||
94 | enum tcpa_pc_event_ids { | 114 | enum tcpa_pc_event_ids { |
95 | SMBIOS = 1, | 115 | SMBIOS = 1, |
96 | BIS_CERT, | 116 | BIS_CERT, |
@@ -100,14 +120,15 @@ enum tcpa_pc_event_ids { | |||
100 | NVRAM, | 120 | NVRAM, |
101 | OPTION_ROM_EXEC, | 121 | OPTION_ROM_EXEC, |
102 | OPTION_ROM_CONFIG, | 122 | OPTION_ROM_CONFIG, |
103 | OPTION_ROM_MICROCODE, | 123 | OPTION_ROM_MICROCODE = 10, |
104 | S_CRTM_VERSION, | 124 | S_CRTM_VERSION, |
105 | S_CRTM_CONTENTS, | 125 | S_CRTM_CONTENTS, |
106 | POST_CONTENTS, | 126 | POST_CONTENTS, |
127 | HOST_TABLE_OF_DEVICES, | ||
107 | }; | 128 | }; |
108 | 129 | ||
109 | static const char* tcpa_pc_event_id_strings[] = { | 130 | static const char* tcpa_pc_event_id_strings[] = { |
110 | "" | 131 | "", |
111 | "SMBIOS", | 132 | "SMBIOS", |
112 | "BIS Certificate", | 133 | "BIS Certificate", |
113 | "POST BIOS ", | 134 | "POST BIOS ", |
@@ -116,10 +137,12 @@ static const char* tcpa_pc_event_id_strings[] = { | |||
116 | "NVRAM", | 137 | "NVRAM", |
117 | "Option ROM", | 138 | "Option ROM", |
118 | "Option ROM config", | 139 | "Option ROM config", |
119 | "Option ROM microcode", | 140 | "", |
141 | "Option ROM microcode ", | ||
120 | "S-CRTM Version", | 142 | "S-CRTM Version", |
121 | "S-CRTM Contents", | 143 | "S-CRTM Contents ", |
122 | "S-CRTM POST Contents", | 144 | "POST Contents ", |
145 | "Table of Devices", | ||
123 | }; | 146 | }; |
124 | 147 | ||
125 | /* returns pointer to start of pos. entry of tcg log */ | 148 | /* returns pointer to start of pos. entry of tcg log */ |
@@ -191,7 +214,7 @@ static int get_event_name(char *dest, struct tcpa_event *event, | |||
191 | const char *name = ""; | 214 | const char *name = ""; |
192 | char data[40] = ""; | 215 | char data[40] = ""; |
193 | int i, n_len = 0, d_len = 0; | 216 | int i, n_len = 0, d_len = 0; |
194 | u32 event_id; | 217 | struct tcpa_pc_event *pc_event; |
195 | 218 | ||
196 | switch(event->event_type) { | 219 | switch(event->event_type) { |
197 | case PREBOOT: | 220 | case PREBOOT: |
@@ -220,31 +243,32 @@ static int get_event_name(char *dest, struct tcpa_event *event, | |||
220 | } | 243 | } |
221 | break; | 244 | break; |
222 | case EVENT_TAG: | 245 | case EVENT_TAG: |
223 | event_id = be32_to_cpu(*((u32 *)event_entry)); | 246 | pc_event = (struct tcpa_pc_event *)event_entry; |
224 | 247 | ||
225 | /* ToDo Row data -> Base64 */ | 248 | /* ToDo Row data -> Base64 */ |
226 | 249 | ||
227 | switch (event_id) { | 250 | switch (pc_event->event_id) { |
228 | case SMBIOS: | 251 | case SMBIOS: |
229 | case BIS_CERT: | 252 | case BIS_CERT: |
230 | case CMOS: | 253 | case CMOS: |
231 | case NVRAM: | 254 | case NVRAM: |
232 | case OPTION_ROM_EXEC: | 255 | case OPTION_ROM_EXEC: |
233 | case OPTION_ROM_CONFIG: | 256 | case OPTION_ROM_CONFIG: |
234 | case OPTION_ROM_MICROCODE: | ||
235 | case S_CRTM_VERSION: | 257 | case S_CRTM_VERSION: |
236 | case S_CRTM_CONTENTS: | 258 | name = tcpa_pc_event_id_strings[pc_event->event_id]; |
237 | case POST_CONTENTS: | ||
238 | name = tcpa_pc_event_id_strings[event_id]; | ||
239 | n_len = strlen(name); | 259 | n_len = strlen(name); |
240 | break; | 260 | break; |
261 | /* hash data */ | ||
241 | case POST_BIOS_ROM: | 262 | case POST_BIOS_ROM: |
242 | case ESCD: | 263 | case ESCD: |
243 | name = tcpa_pc_event_id_strings[event_id]; | 264 | case OPTION_ROM_MICROCODE: |
265 | case S_CRTM_CONTENTS: | ||
266 | case POST_CONTENTS: | ||
267 | name = tcpa_pc_event_id_strings[pc_event->event_id]; | ||
244 | n_len = strlen(name); | 268 | n_len = strlen(name); |
245 | for (i = 0; i < 20; i++) | 269 | for (i = 0; i < 20; i++) |
246 | d_len += sprintf(data, "%02x", | 270 | d_len += sprintf(&data[2*i], "%02x", |
247 | event_entry[8 + i]); | 271 | pc_event->event_data[i]); |
248 | break; | 272 | break; |
249 | default: | 273 | default: |
250 | break; | 274 | break; |
@@ -260,52 +284,13 @@ static int get_event_name(char *dest, struct tcpa_event *event, | |||
260 | 284 | ||
261 | static int tpm_binary_bios_measurements_show(struct seq_file *m, void *v) | 285 | static int tpm_binary_bios_measurements_show(struct seq_file *m, void *v) |
262 | { | 286 | { |
287 | struct tcpa_event *event = v; | ||
288 | char *data = v; | ||
289 | int i; | ||
263 | 290 | ||
264 | char *eventname; | 291 | for (i = 0; i < sizeof(struct tcpa_event) + event->event_size; i++) |
265 | char data[4]; | ||
266 | u32 help; | ||
267 | int i, len; | ||
268 | struct tcpa_event *event = (struct tcpa_event *) v; | ||
269 | unsigned char *event_entry = | ||
270 | (unsigned char *) (v + sizeof(struct tcpa_event)); | ||
271 | |||
272 | eventname = kmalloc(MAX_TEXT_EVENT, GFP_KERNEL); | ||
273 | if (!eventname) { | ||
274 | printk(KERN_ERR "%s: ERROR - No Memory for event name\n ", | ||
275 | __func__); | ||
276 | return -ENOMEM; | ||
277 | } | ||
278 | |||
279 | /* 1st: PCR used is in little-endian format (4 bytes) */ | ||
280 | help = le32_to_cpu(event->pcr_index); | ||
281 | memcpy(data, &help, 4); | ||
282 | for (i = 0; i < 4; i++) | ||
283 | seq_putc(m, data[i]); | ||
284 | |||
285 | /* 2nd: SHA1 (20 bytes) */ | ||
286 | for (i = 0; i < 20; i++) | ||
287 | seq_putc(m, event->pcr_value[i]); | ||
288 | |||
289 | /* 3rd: event type identifier (4 bytes) */ | ||
290 | help = le32_to_cpu(event->event_type); | ||
291 | memcpy(data, &help, 4); | ||
292 | for (i = 0; i < 4; i++) | ||
293 | seq_putc(m, data[i]); | 292 | seq_putc(m, data[i]); |
294 | 293 | ||
295 | len = 0; | ||
296 | |||
297 | len += get_event_name(eventname, event, event_entry); | ||
298 | |||
299 | /* 4th: filename <= 255 + \'0' delimiter */ | ||
300 | if (len > TCG_EVENT_NAME_LEN_MAX) | ||
301 | len = TCG_EVENT_NAME_LEN_MAX; | ||
302 | |||
303 | for (i = 0; i < len; i++) | ||
304 | seq_putc(m, eventname[i]); | ||
305 | |||
306 | /* 5th: delimiter */ | ||
307 | seq_putc(m, '\0'); | ||
308 | |||
309 | return 0; | 294 | return 0; |
310 | } | 295 | } |
311 | 296 | ||
@@ -353,6 +338,7 @@ static int tpm_ascii_bios_measurements_show(struct seq_file *m, void *v) | |||
353 | /* 4th: eventname <= max + \'0' delimiter */ | 338 | /* 4th: eventname <= max + \'0' delimiter */ |
354 | seq_printf(m, " %s\n", eventname); | 339 | seq_printf(m, " %s\n", eventname); |
355 | 340 | ||
341 | kfree(eventname); | ||
356 | return 0; | 342 | return 0; |
357 | } | 343 | } |
358 | 344 | ||
@@ -376,6 +362,7 @@ static int read_log(struct tpm_bios_log *log) | |||
376 | struct acpi_tcpa *buff; | 362 | struct acpi_tcpa *buff; |
377 | acpi_status status; | 363 | acpi_status status; |
378 | struct acpi_table_header *virt; | 364 | struct acpi_table_header *virt; |
365 | u64 len, start; | ||
379 | 366 | ||
380 | if (log->bios_event_log != NULL) { | 367 | if (log->bios_event_log != NULL) { |
381 | printk(KERN_ERR | 368 | printk(KERN_ERR |
@@ -396,27 +383,37 @@ static int read_log(struct tpm_bios_log *log) | |||
396 | return -EIO; | 383 | return -EIO; |
397 | } | 384 | } |
398 | 385 | ||
399 | if (buff->log_max_len == 0) { | 386 | switch(buff->platform_class) { |
387 | case BIOS_SERVER: | ||
388 | len = buff->server.log_max_len; | ||
389 | start = buff->server.log_start_addr; | ||
390 | break; | ||
391 | case BIOS_CLIENT: | ||
392 | default: | ||
393 | len = buff->client.log_max_len; | ||
394 | start = buff->client.log_start_addr; | ||
395 | break; | ||
396 | } | ||
397 | if (!len) { | ||
400 | printk(KERN_ERR "%s: ERROR - TCPA log area empty\n", __func__); | 398 | printk(KERN_ERR "%s: ERROR - TCPA log area empty\n", __func__); |
401 | return -EIO; | 399 | return -EIO; |
402 | } | 400 | } |
403 | 401 | ||
404 | /* malloc EventLog space */ | 402 | /* malloc EventLog space */ |
405 | log->bios_event_log = kmalloc(buff->log_max_len, GFP_KERNEL); | 403 | log->bios_event_log = kmalloc(len, GFP_KERNEL); |
406 | if (!log->bios_event_log) { | 404 | if (!log->bios_event_log) { |
407 | printk | 405 | printk("%s: ERROR - Not enough Memory for BIOS measurements\n", |
408 | ("%s: ERROR - Not enough Memory for BIOS measurements\n", | 406 | __func__); |
409 | __func__); | ||
410 | return -ENOMEM; | 407 | return -ENOMEM; |
411 | } | 408 | } |
412 | 409 | ||
413 | log->bios_event_log_end = log->bios_event_log + buff->log_max_len; | 410 | log->bios_event_log_end = log->bios_event_log + len; |
414 | 411 | ||
415 | acpi_os_map_memory(buff->log_start_addr, buff->log_max_len, (void *) &virt); | 412 | acpi_os_map_memory(start, len, (void *) &virt); |
416 | 413 | ||
417 | memcpy(log->bios_event_log, virt, buff->log_max_len); | 414 | memcpy(log->bios_event_log, virt, len); |
418 | 415 | ||
419 | acpi_os_unmap_memory(virt, buff->log_max_len); | 416 | acpi_os_unmap_memory(virt, len); |
420 | return 0; | 417 | return 0; |
421 | } | 418 | } |
422 | 419 | ||