diff options
author | Hon Ching \(Vicky\) Lo <honclo@linux.vnet.ibm.com> | 2015-06-17 18:17:08 -0400 |
---|---|---|
committer | Peter Huewe <peterhuewe@gmx.de> | 2015-10-18 19:09:30 -0400 |
commit | 0cc698af36ff22295dce2f5e46b0cfe605789fa4 (patch) | |
tree | cec30aa92173479c797cc0349a0536b5849637c8 | |
parent | 09e23a4a5dc39ef874403f3f6fa419f49db3677a (diff) |
vTPM: support little endian guests
This patch makes the code endianness independent. We defined a
macro do_endian_conversion to apply endianness to raw integers
in the event entries so that they will be displayed properly.
tpm_binary_bios_measurements_show() is modified for the display.
Signed-off-by: Hon Ching(Vicky) Lo <honclo@linux.vnet.ibm.com>
Signed-off-by: Joy Latten <jmlatten@linux.vnet.ibm.com>
Reviewed-by: Ashley Lai <ashley@ahsleylai.com>
Reviewed-by: Ashley Lai <ashley@ahsleylai.com>
Signed-off-by: Peter Huewe <peterhuewe@gmx.de>
-rw-r--r-- | drivers/char/tpm/tpm_eventlog.c | 78 | ||||
-rw-r--r-- | drivers/char/tpm/tpm_eventlog.h | 6 |
2 files changed, 62 insertions, 22 deletions
diff --git a/drivers/char/tpm/tpm_eventlog.c b/drivers/char/tpm/tpm_eventlog.c index 3a56a131586c..bd72fb04225e 100644 --- a/drivers/char/tpm/tpm_eventlog.c +++ b/drivers/char/tpm/tpm_eventlog.c | |||
@@ -76,15 +76,25 @@ static void *tpm_bios_measurements_start(struct seq_file *m, loff_t *pos) | |||
76 | void *addr = log->bios_event_log; | 76 | void *addr = log->bios_event_log; |
77 | void *limit = log->bios_event_log_end; | 77 | void *limit = log->bios_event_log_end; |
78 | struct tcpa_event *event; | 78 | struct tcpa_event *event; |
79 | u32 converted_event_size; | ||
80 | u32 converted_event_type; | ||
81 | |||
79 | 82 | ||
80 | /* read over *pos measurements */ | 83 | /* read over *pos measurements */ |
81 | for (i = 0; i < *pos; i++) { | 84 | for (i = 0; i < *pos; i++) { |
82 | event = addr; | 85 | event = addr; |
83 | 86 | ||
87 | converted_event_size = | ||
88 | do_endian_conversion(event->event_size); | ||
89 | converted_event_type = | ||
90 | do_endian_conversion(event->event_type); | ||
91 | |||
84 | if ((addr + sizeof(struct tcpa_event)) < limit) { | 92 | if ((addr + sizeof(struct tcpa_event)) < limit) { |
85 | if (event->event_type == 0 && event->event_size == 0) | 93 | if ((converted_event_type == 0) && |
94 | (converted_event_size == 0)) | ||
86 | return NULL; | 95 | return NULL; |
87 | addr += sizeof(struct tcpa_event) + event->event_size; | 96 | addr += (sizeof(struct tcpa_event) + |
97 | converted_event_size); | ||
88 | } | 98 | } |
89 | } | 99 | } |
90 | 100 | ||
@@ -94,8 +104,12 @@ static void *tpm_bios_measurements_start(struct seq_file *m, loff_t *pos) | |||
94 | 104 | ||
95 | event = addr; | 105 | event = addr; |
96 | 106 | ||
97 | if ((event->event_type == 0 && event->event_size == 0) || | 107 | converted_event_size = do_endian_conversion(event->event_size); |
98 | ((addr + sizeof(struct tcpa_event) + event->event_size) >= limit)) | 108 | converted_event_type = do_endian_conversion(event->event_type); |
109 | |||
110 | if (((converted_event_type == 0) && (converted_event_size == 0)) | ||
111 | || ((addr + sizeof(struct tcpa_event) + converted_event_size) | ||
112 | >= limit)) | ||
99 | return NULL; | 113 | return NULL; |
100 | 114 | ||
101 | return addr; | 115 | return addr; |
@@ -107,8 +121,12 @@ static void *tpm_bios_measurements_next(struct seq_file *m, void *v, | |||
107 | struct tcpa_event *event = v; | 121 | struct tcpa_event *event = v; |
108 | struct tpm_bios_log *log = m->private; | 122 | struct tpm_bios_log *log = m->private; |
109 | void *limit = log->bios_event_log_end; | 123 | void *limit = log->bios_event_log_end; |
124 | u32 converted_event_size; | ||
125 | u32 converted_event_type; | ||
110 | 126 | ||
111 | v += sizeof(struct tcpa_event) + event->event_size; | 127 | converted_event_size = do_endian_conversion(event->event_size); |
128 | |||
129 | v += sizeof(struct tcpa_event) + converted_event_size; | ||
112 | 130 | ||
113 | /* now check if current entry is valid */ | 131 | /* now check if current entry is valid */ |
114 | if ((v + sizeof(struct tcpa_event)) >= limit) | 132 | if ((v + sizeof(struct tcpa_event)) >= limit) |
@@ -116,11 +134,11 @@ static void *tpm_bios_measurements_next(struct seq_file *m, void *v, | |||
116 | 134 | ||
117 | event = v; | 135 | event = v; |
118 | 136 | ||
119 | if (event->event_type == 0 && event->event_size == 0) | 137 | converted_event_size = do_endian_conversion(event->event_size); |
120 | return NULL; | 138 | converted_event_type = do_endian_conversion(event->event_type); |
121 | 139 | ||
122 | if ((event->event_type == 0 && event->event_size == 0) || | 140 | if (((converted_event_type == 0) && (converted_event_size == 0)) || |
123 | ((v + sizeof(struct tcpa_event) + event->event_size) >= limit)) | 141 | ((v + sizeof(struct tcpa_event) + converted_event_size) >= limit)) |
124 | return NULL; | 142 | return NULL; |
125 | 143 | ||
126 | (*pos)++; | 144 | (*pos)++; |
@@ -140,7 +158,7 @@ static int get_event_name(char *dest, struct tcpa_event *event, | |||
140 | int i, n_len = 0, d_len = 0; | 158 | int i, n_len = 0, d_len = 0; |
141 | struct tcpa_pc_event *pc_event; | 159 | struct tcpa_pc_event *pc_event; |
142 | 160 | ||
143 | switch(event->event_type) { | 161 | switch (do_endian_conversion(event->event_type)) { |
144 | case PREBOOT: | 162 | case PREBOOT: |
145 | case POST_CODE: | 163 | case POST_CODE: |
146 | case UNUSED: | 164 | case UNUSED: |
@@ -156,14 +174,16 @@ static int get_event_name(char *dest, struct tcpa_event *event, | |||
156 | case NONHOST_CODE: | 174 | case NONHOST_CODE: |
157 | case NONHOST_CONFIG: | 175 | case NONHOST_CONFIG: |
158 | case NONHOST_INFO: | 176 | case NONHOST_INFO: |
159 | name = tcpa_event_type_strings[event->event_type]; | 177 | name = tcpa_event_type_strings[do_endian_conversion |
178 | (event->event_type)]; | ||
160 | n_len = strlen(name); | 179 | n_len = strlen(name); |
161 | break; | 180 | break; |
162 | case SEPARATOR: | 181 | case SEPARATOR: |
163 | case ACTION: | 182 | case ACTION: |
164 | if (MAX_TEXT_EVENT > event->event_size) { | 183 | if (MAX_TEXT_EVENT > |
184 | do_endian_conversion(event->event_size)) { | ||
165 | name = event_entry; | 185 | name = event_entry; |
166 | n_len = event->event_size; | 186 | n_len = do_endian_conversion(event->event_size); |
167 | } | 187 | } |
168 | break; | 188 | break; |
169 | case EVENT_TAG: | 189 | case EVENT_TAG: |
@@ -171,7 +191,7 @@ static int get_event_name(char *dest, struct tcpa_event *event, | |||
171 | 191 | ||
172 | /* ToDo Row data -> Base64 */ | 192 | /* ToDo Row data -> Base64 */ |
173 | 193 | ||
174 | switch (pc_event->event_id) { | 194 | switch (do_endian_conversion(pc_event->event_id)) { |
175 | case SMBIOS: | 195 | case SMBIOS: |
176 | case BIS_CERT: | 196 | case BIS_CERT: |
177 | case CMOS: | 197 | case CMOS: |
@@ -179,7 +199,8 @@ static int get_event_name(char *dest, struct tcpa_event *event, | |||
179 | case OPTION_ROM_EXEC: | 199 | case OPTION_ROM_EXEC: |
180 | case OPTION_ROM_CONFIG: | 200 | case OPTION_ROM_CONFIG: |
181 | case S_CRTM_VERSION: | 201 | case S_CRTM_VERSION: |
182 | name = tcpa_pc_event_id_strings[pc_event->event_id]; | 202 | name = tcpa_pc_event_id_strings[do_endian_conversion |
203 | (pc_event->event_id)]; | ||
183 | n_len = strlen(name); | 204 | n_len = strlen(name); |
184 | break; | 205 | break; |
185 | /* hash data */ | 206 | /* hash data */ |
@@ -188,7 +209,8 @@ static int get_event_name(char *dest, struct tcpa_event *event, | |||
188 | case OPTION_ROM_MICROCODE: | 209 | case OPTION_ROM_MICROCODE: |
189 | case S_CRTM_CONTENTS: | 210 | case S_CRTM_CONTENTS: |
190 | case POST_CONTENTS: | 211 | case POST_CONTENTS: |
191 | name = tcpa_pc_event_id_strings[pc_event->event_id]; | 212 | name = tcpa_pc_event_id_strings[do_endian_conversion |
213 | (pc_event->event_id)]; | ||
192 | n_len = strlen(name); | 214 | n_len = strlen(name); |
193 | for (i = 0; i < 20; i++) | 215 | for (i = 0; i < 20; i++) |
194 | d_len += sprintf(&data[2*i], "%02x", | 216 | d_len += sprintf(&data[2*i], "%02x", |
@@ -209,13 +231,24 @@ static int get_event_name(char *dest, struct tcpa_event *event, | |||
209 | static int tpm_binary_bios_measurements_show(struct seq_file *m, void *v) | 231 | static int tpm_binary_bios_measurements_show(struct seq_file *m, void *v) |
210 | { | 232 | { |
211 | struct tcpa_event *event = v; | 233 | struct tcpa_event *event = v; |
212 | char *data = v; | 234 | struct tcpa_event temp_event; |
235 | char *tempPtr; | ||
213 | int i; | 236 | int i; |
214 | 237 | ||
215 | for (i = 0; i < sizeof(struct tcpa_event) + event->event_size; i++) | 238 | memcpy(&temp_event, event, sizeof(struct tcpa_event)); |
216 | seq_putc(m, data[i]); | 239 | |
240 | /* convert raw integers for endianness */ | ||
241 | temp_event.pcr_index = do_endian_conversion(event->pcr_index); | ||
242 | temp_event.event_type = do_endian_conversion(event->event_type); | ||
243 | temp_event.event_size = do_endian_conversion(event->event_size); | ||
244 | |||
245 | tempPtr = (char *)&temp_event; | ||
246 | |||
247 | for (i = 0; i < sizeof(struct tcpa_event) + temp_event.event_size; i++) | ||
248 | seq_putc(m, tempPtr[i]); | ||
217 | 249 | ||
218 | return 0; | 250 | return 0; |
251 | |||
219 | } | 252 | } |
220 | 253 | ||
221 | static int tpm_bios_measurements_release(struct inode *inode, | 254 | static int tpm_bios_measurements_release(struct inode *inode, |
@@ -238,7 +271,7 @@ static int tpm_ascii_bios_measurements_show(struct seq_file *m, void *v) | |||
238 | char *eventname; | 271 | char *eventname; |
239 | struct tcpa_event *event = v; | 272 | struct tcpa_event *event = v; |
240 | unsigned char *event_entry = | 273 | unsigned char *event_entry = |
241 | (unsigned char *) (v + sizeof(struct tcpa_event)); | 274 | (unsigned char *)(v + sizeof(struct tcpa_event)); |
242 | 275 | ||
243 | eventname = kmalloc(MAX_TEXT_EVENT, GFP_KERNEL); | 276 | eventname = kmalloc(MAX_TEXT_EVENT, GFP_KERNEL); |
244 | if (!eventname) { | 277 | if (!eventname) { |
@@ -247,13 +280,14 @@ static int tpm_ascii_bios_measurements_show(struct seq_file *m, void *v) | |||
247 | return -EFAULT; | 280 | return -EFAULT; |
248 | } | 281 | } |
249 | 282 | ||
250 | seq_printf(m, "%2d ", event->pcr_index); | 283 | /* 1st: PCR */ |
284 | seq_printf(m, "%2d ", do_endian_conversion(event->pcr_index)); | ||
251 | 285 | ||
252 | /* 2nd: SHA1 */ | 286 | /* 2nd: SHA1 */ |
253 | seq_printf(m, "%20phN", event->pcr_value); | 287 | seq_printf(m, "%20phN", event->pcr_value); |
254 | 288 | ||
255 | /* 3rd: event type identifier */ | 289 | /* 3rd: event type identifier */ |
256 | seq_printf(m, " %02x", event->event_type); | 290 | seq_printf(m, " %02x", do_endian_conversion(event->event_type)); |
257 | 291 | ||
258 | len += get_event_name(eventname, event, event_entry); | 292 | len += get_event_name(eventname, event, event_entry); |
259 | 293 | ||
diff --git a/drivers/char/tpm/tpm_eventlog.h b/drivers/char/tpm/tpm_eventlog.h index e7da086d6928..267bfbd1b7bb 100644 --- a/drivers/char/tpm/tpm_eventlog.h +++ b/drivers/char/tpm/tpm_eventlog.h | |||
@@ -6,6 +6,12 @@ | |||
6 | #define MAX_TEXT_EVENT 1000 /* Max event string length */ | 6 | #define MAX_TEXT_EVENT 1000 /* Max event string length */ |
7 | #define ACPI_TCPA_SIG "TCPA" /* 0x41504354 /'TCPA' */ | 7 | #define ACPI_TCPA_SIG "TCPA" /* 0x41504354 /'TCPA' */ |
8 | 8 | ||
9 | #ifdef CONFIG_PPC64 | ||
10 | #define do_endian_conversion(x) be32_to_cpu(x) | ||
11 | #else | ||
12 | #define do_endian_conversion(x) x | ||
13 | #endif | ||
14 | |||
9 | enum bios_platform_class { | 15 | enum bios_platform_class { |
10 | BIOS_CLIENT = 0x00, | 16 | BIOS_CLIENT = 0x00, |
11 | BIOS_SERVER = 0x01, | 17 | BIOS_SERVER = 0x01, |