.. | .. |
---|
29 | 29 | #include <asm/checksum.h> |
---|
30 | 30 | #include <asm/debug.h> |
---|
31 | 31 | #include <asm/os_info.h> |
---|
| 32 | +#include <asm/sections.h> |
---|
| 33 | +#include <asm/boot_data.h> |
---|
32 | 34 | #include "entry.h" |
---|
33 | 35 | |
---|
34 | 36 | #define IPL_PARM_BLOCK_VERSION 0 |
---|
.. | .. |
---|
37 | 39 | #define IPL_CCW_STR "ccw" |
---|
38 | 40 | #define IPL_FCP_STR "fcp" |
---|
39 | 41 | #define IPL_FCP_DUMP_STR "fcp_dump" |
---|
| 42 | +#define IPL_NVME_STR "nvme" |
---|
| 43 | +#define IPL_NVME_DUMP_STR "nvme_dump" |
---|
40 | 44 | #define IPL_NSS_STR "nss" |
---|
41 | 45 | |
---|
42 | 46 | #define DUMP_CCW_STR "ccw" |
---|
43 | 47 | #define DUMP_FCP_STR "fcp" |
---|
| 48 | +#define DUMP_NVME_STR "nvme" |
---|
44 | 49 | #define DUMP_NONE_STR "none" |
---|
45 | 50 | |
---|
46 | 51 | /* |
---|
.. | .. |
---|
91 | 96 | return IPL_FCP_DUMP_STR; |
---|
92 | 97 | case IPL_TYPE_NSS: |
---|
93 | 98 | return IPL_NSS_STR; |
---|
| 99 | + case IPL_TYPE_NVME: |
---|
| 100 | + return IPL_NVME_STR; |
---|
| 101 | + case IPL_TYPE_NVME_DUMP: |
---|
| 102 | + return IPL_NVME_DUMP_STR; |
---|
94 | 103 | case IPL_TYPE_UNKNOWN: |
---|
95 | 104 | default: |
---|
96 | 105 | return IPL_UNKNOWN_STR; |
---|
.. | .. |
---|
101 | 110 | DUMP_TYPE_NONE = 1, |
---|
102 | 111 | DUMP_TYPE_CCW = 2, |
---|
103 | 112 | DUMP_TYPE_FCP = 4, |
---|
| 113 | + DUMP_TYPE_NVME = 8, |
---|
104 | 114 | }; |
---|
105 | 115 | |
---|
106 | 116 | static char *dump_type_str(enum dump_type type) |
---|
.. | .. |
---|
112 | 122 | return DUMP_CCW_STR; |
---|
113 | 123 | case DUMP_TYPE_FCP: |
---|
114 | 124 | return DUMP_FCP_STR; |
---|
| 125 | + case DUMP_TYPE_NVME: |
---|
| 126 | + return DUMP_NVME_STR; |
---|
115 | 127 | default: |
---|
116 | 128 | return NULL; |
---|
117 | 129 | } |
---|
118 | 130 | } |
---|
119 | 131 | |
---|
120 | | -static int ipl_block_valid; |
---|
121 | | -static struct ipl_parameter_block ipl_block; |
---|
| 132 | +int __bootdata_preserved(ipl_block_valid); |
---|
| 133 | +struct ipl_parameter_block __bootdata_preserved(ipl_block); |
---|
| 134 | +int __bootdata_preserved(ipl_secure_flag); |
---|
| 135 | + |
---|
| 136 | +unsigned long __bootdata_preserved(ipl_cert_list_addr); |
---|
| 137 | +unsigned long __bootdata_preserved(ipl_cert_list_size); |
---|
| 138 | + |
---|
| 139 | +unsigned long __bootdata(early_ipl_comp_list_addr); |
---|
| 140 | +unsigned long __bootdata(early_ipl_comp_list_size); |
---|
122 | 141 | |
---|
123 | 142 | static int reipl_capabilities = IPL_TYPE_UNKNOWN; |
---|
124 | 143 | |
---|
125 | 144 | static enum ipl_type reipl_type = IPL_TYPE_UNKNOWN; |
---|
126 | 145 | static struct ipl_parameter_block *reipl_block_fcp; |
---|
| 146 | +static struct ipl_parameter_block *reipl_block_nvme; |
---|
127 | 147 | static struct ipl_parameter_block *reipl_block_ccw; |
---|
128 | 148 | static struct ipl_parameter_block *reipl_block_nss; |
---|
129 | 149 | static struct ipl_parameter_block *reipl_block_actual; |
---|
.. | .. |
---|
131 | 151 | static int dump_capabilities = DUMP_TYPE_NONE; |
---|
132 | 152 | static enum dump_type dump_type = DUMP_TYPE_NONE; |
---|
133 | 153 | static struct ipl_parameter_block *dump_block_fcp; |
---|
| 154 | +static struct ipl_parameter_block *dump_block_nvme; |
---|
134 | 155 | static struct ipl_parameter_block *dump_block_ccw; |
---|
135 | 156 | |
---|
136 | 157 | static struct sclp_ipl_info sclp_ipl_info; |
---|
| 158 | + |
---|
| 159 | +static bool reipl_nvme_clear; |
---|
| 160 | +static bool reipl_fcp_clear; |
---|
| 161 | +static bool reipl_ccw_clear; |
---|
137 | 162 | |
---|
138 | 163 | static inline int __diag308(unsigned long subcode, void *addr) |
---|
139 | 164 | { |
---|
.. | .. |
---|
151 | 176 | |
---|
152 | 177 | int diag308(unsigned long subcode, void *addr) |
---|
153 | 178 | { |
---|
| 179 | + if (IS_ENABLED(CONFIG_KASAN)) |
---|
| 180 | + __arch_local_irq_stosm(0x04); /* enable DAT */ |
---|
154 | 181 | diag_stat_inc(DIAG_STAT_X308); |
---|
155 | 182 | return __diag308(subcode, addr); |
---|
156 | 183 | } |
---|
.. | .. |
---|
163 | 190 | struct kobj_attribute *attr, \ |
---|
164 | 191 | char *page) \ |
---|
165 | 192 | { \ |
---|
166 | | - return snprintf(page, PAGE_SIZE, _format, ##args); \ |
---|
| 193 | + return scnprintf(page, PAGE_SIZE, _format, ##args); \ |
---|
167 | 194 | } |
---|
168 | 195 | |
---|
169 | 196 | #define IPL_ATTR_CCW_STORE_FN(_prefix, _name, _ipl_blk) \ |
---|
.. | .. |
---|
239 | 266 | if (!ipl_block_valid) |
---|
240 | 267 | return IPL_TYPE_UNKNOWN; |
---|
241 | 268 | |
---|
242 | | - switch (ipl_block.hdr.pbt) { |
---|
243 | | - case DIAG308_IPL_TYPE_CCW: |
---|
| 269 | + switch (ipl_block.pb0_hdr.pbt) { |
---|
| 270 | + case IPL_PBT_CCW: |
---|
244 | 271 | return IPL_TYPE_CCW; |
---|
245 | | - case DIAG308_IPL_TYPE_FCP: |
---|
246 | | - if (ipl_block.ipl_info.fcp.opt == DIAG308_IPL_OPT_DUMP) |
---|
| 272 | + case IPL_PBT_FCP: |
---|
| 273 | + if (ipl_block.fcp.opt == IPL_PB0_FCP_OPT_DUMP) |
---|
247 | 274 | return IPL_TYPE_FCP_DUMP; |
---|
248 | 275 | else |
---|
249 | 276 | return IPL_TYPE_FCP; |
---|
| 277 | + case IPL_PBT_NVME: |
---|
| 278 | + if (ipl_block.nvme.opt == IPL_PB0_NVME_OPT_DUMP) |
---|
| 279 | + return IPL_TYPE_NVME_DUMP; |
---|
| 280 | + else |
---|
| 281 | + return IPL_TYPE_NVME; |
---|
250 | 282 | } |
---|
251 | 283 | return IPL_TYPE_UNKNOWN; |
---|
252 | 284 | } |
---|
.. | .. |
---|
262 | 294 | |
---|
263 | 295 | static struct kobj_attribute sys_ipl_type_attr = __ATTR_RO(ipl_type); |
---|
264 | 296 | |
---|
265 | | -/* VM IPL PARM routines */ |
---|
266 | | -static size_t reipl_get_ascii_vmparm(char *dest, size_t size, |
---|
267 | | - const struct ipl_parameter_block *ipb) |
---|
| 297 | +static ssize_t ipl_secure_show(struct kobject *kobj, |
---|
| 298 | + struct kobj_attribute *attr, char *page) |
---|
268 | 299 | { |
---|
269 | | - int i; |
---|
270 | | - size_t len; |
---|
271 | | - char has_lowercase = 0; |
---|
272 | | - |
---|
273 | | - len = 0; |
---|
274 | | - if ((ipb->ipl_info.ccw.vm_flags & DIAG308_VM_FLAGS_VP_VALID) && |
---|
275 | | - (ipb->ipl_info.ccw.vm_parm_len > 0)) { |
---|
276 | | - |
---|
277 | | - len = min_t(size_t, size - 1, ipb->ipl_info.ccw.vm_parm_len); |
---|
278 | | - memcpy(dest, ipb->ipl_info.ccw.vm_parm, len); |
---|
279 | | - /* If at least one character is lowercase, we assume mixed |
---|
280 | | - * case; otherwise we convert everything to lowercase. |
---|
281 | | - */ |
---|
282 | | - for (i = 0; i < len; i++) |
---|
283 | | - if ((dest[i] > 0x80 && dest[i] < 0x8a) || /* a-i */ |
---|
284 | | - (dest[i] > 0x90 && dest[i] < 0x9a) || /* j-r */ |
---|
285 | | - (dest[i] > 0xa1 && dest[i] < 0xaa)) { /* s-z */ |
---|
286 | | - has_lowercase = 1; |
---|
287 | | - break; |
---|
288 | | - } |
---|
289 | | - if (!has_lowercase) |
---|
290 | | - EBC_TOLOWER(dest, len); |
---|
291 | | - EBCASC(dest, len); |
---|
292 | | - } |
---|
293 | | - dest[len] = 0; |
---|
294 | | - |
---|
295 | | - return len; |
---|
| 300 | + return sprintf(page, "%i\n", !!ipl_secure_flag); |
---|
296 | 301 | } |
---|
297 | 302 | |
---|
298 | | -size_t append_ipl_vmparm(char *dest, size_t size) |
---|
299 | | -{ |
---|
300 | | - size_t rc; |
---|
| 303 | +static struct kobj_attribute sys_ipl_secure_attr = |
---|
| 304 | + __ATTR(secure, 0444, ipl_secure_show, NULL); |
---|
301 | 305 | |
---|
302 | | - rc = 0; |
---|
303 | | - if (ipl_block_valid && ipl_block.hdr.pbt == DIAG308_IPL_TYPE_CCW) |
---|
304 | | - rc = reipl_get_ascii_vmparm(dest, size, &ipl_block); |
---|
305 | | - else |
---|
306 | | - dest[0] = 0; |
---|
307 | | - return rc; |
---|
| 306 | +static ssize_t ipl_has_secure_show(struct kobject *kobj, |
---|
| 307 | + struct kobj_attribute *attr, char *page) |
---|
| 308 | +{ |
---|
| 309 | + return sprintf(page, "%i\n", !!sclp.has_sipl); |
---|
308 | 310 | } |
---|
| 311 | + |
---|
| 312 | +static struct kobj_attribute sys_ipl_has_secure_attr = |
---|
| 313 | + __ATTR(has_secure, 0444, ipl_has_secure_show, NULL); |
---|
309 | 314 | |
---|
310 | 315 | static ssize_t ipl_vm_parm_show(struct kobject *kobj, |
---|
311 | 316 | struct kobj_attribute *attr, char *page) |
---|
312 | 317 | { |
---|
313 | 318 | char parm[DIAG308_VMPARM_SIZE + 1] = {}; |
---|
314 | 319 | |
---|
315 | | - append_ipl_vmparm(parm, sizeof(parm)); |
---|
| 320 | + if (ipl_block_valid && (ipl_block.pb0_hdr.pbt == IPL_PBT_CCW)) |
---|
| 321 | + ipl_block_get_ascii_vmparm(parm, sizeof(parm), &ipl_block); |
---|
316 | 322 | return sprintf(page, "%s\n", parm); |
---|
317 | 323 | } |
---|
318 | | - |
---|
319 | | -static size_t scpdata_length(const char* buf, size_t count) |
---|
320 | | -{ |
---|
321 | | - while (count) { |
---|
322 | | - if (buf[count - 1] != '\0' && buf[count - 1] != ' ') |
---|
323 | | - break; |
---|
324 | | - count--; |
---|
325 | | - } |
---|
326 | | - return count; |
---|
327 | | -} |
---|
328 | | - |
---|
329 | | -static size_t reipl_append_ascii_scpdata(char *dest, size_t size, |
---|
330 | | - const struct ipl_parameter_block *ipb) |
---|
331 | | -{ |
---|
332 | | - size_t count; |
---|
333 | | - size_t i; |
---|
334 | | - int has_lowercase; |
---|
335 | | - |
---|
336 | | - count = min(size - 1, scpdata_length(ipb->ipl_info.fcp.scp_data, |
---|
337 | | - ipb->ipl_info.fcp.scp_data_len)); |
---|
338 | | - if (!count) |
---|
339 | | - goto out; |
---|
340 | | - |
---|
341 | | - has_lowercase = 0; |
---|
342 | | - for (i = 0; i < count; i++) { |
---|
343 | | - if (!isascii(ipb->ipl_info.fcp.scp_data[i])) { |
---|
344 | | - count = 0; |
---|
345 | | - goto out; |
---|
346 | | - } |
---|
347 | | - if (!has_lowercase && islower(ipb->ipl_info.fcp.scp_data[i])) |
---|
348 | | - has_lowercase = 1; |
---|
349 | | - } |
---|
350 | | - |
---|
351 | | - if (has_lowercase) |
---|
352 | | - memcpy(dest, ipb->ipl_info.fcp.scp_data, count); |
---|
353 | | - else |
---|
354 | | - for (i = 0; i < count; i++) |
---|
355 | | - dest[i] = tolower(ipb->ipl_info.fcp.scp_data[i]); |
---|
356 | | -out: |
---|
357 | | - dest[count] = '\0'; |
---|
358 | | - return count; |
---|
359 | | -} |
---|
360 | | - |
---|
361 | | -size_t append_ipl_scpdata(char *dest, size_t len) |
---|
362 | | -{ |
---|
363 | | - size_t rc; |
---|
364 | | - |
---|
365 | | - rc = 0; |
---|
366 | | - if (ipl_block_valid && ipl_block.hdr.pbt == DIAG308_IPL_TYPE_FCP) |
---|
367 | | - rc = reipl_append_ascii_scpdata(dest, len, &ipl_block); |
---|
368 | | - else |
---|
369 | | - dest[0] = 0; |
---|
370 | | - return rc; |
---|
371 | | -} |
---|
372 | | - |
---|
373 | 324 | |
---|
374 | 325 | static struct kobj_attribute sys_ipl_vm_parm_attr = |
---|
375 | 326 | __ATTR(parm, S_IRUGO, ipl_vm_parm_show, NULL); |
---|
.. | .. |
---|
379 | 330 | { |
---|
380 | 331 | switch (ipl_info.type) { |
---|
381 | 332 | case IPL_TYPE_CCW: |
---|
382 | | - return sprintf(page, "0.%x.%04x\n", ipl_block.ipl_info.ccw.ssid, |
---|
383 | | - ipl_block.ipl_info.ccw.devno); |
---|
| 333 | + return sprintf(page, "0.%x.%04x\n", ipl_block.ccw.ssid, |
---|
| 334 | + ipl_block.ccw.devno); |
---|
384 | 335 | case IPL_TYPE_FCP: |
---|
385 | 336 | case IPL_TYPE_FCP_DUMP: |
---|
386 | | - return sprintf(page, "0.0.%04x\n", |
---|
387 | | - ipl_block.ipl_info.fcp.devno); |
---|
| 337 | + return sprintf(page, "0.0.%04x\n", ipl_block.fcp.devno); |
---|
| 338 | + case IPL_TYPE_NVME: |
---|
| 339 | + case IPL_TYPE_NVME_DUMP: |
---|
| 340 | + return sprintf(page, "%08ux\n", ipl_block.nvme.fid); |
---|
388 | 341 | default: |
---|
389 | 342 | return 0; |
---|
390 | 343 | } |
---|
.. | .. |
---|
408 | 361 | struct bin_attribute *attr, char *buf, |
---|
409 | 362 | loff_t off, size_t count) |
---|
410 | 363 | { |
---|
411 | | - unsigned int size = ipl_block.ipl_info.fcp.scp_data_len; |
---|
412 | | - void *scp_data = &ipl_block.ipl_info.fcp.scp_data; |
---|
| 364 | + unsigned int size = ipl_block.fcp.scp_data_len; |
---|
| 365 | + void *scp_data = &ipl_block.fcp.scp_data; |
---|
413 | 366 | |
---|
414 | 367 | return memory_read_from_buffer(buf, count, &off, scp_data, size); |
---|
415 | 368 | } |
---|
| 369 | + |
---|
| 370 | +static ssize_t ipl_nvme_scp_data_read(struct file *filp, struct kobject *kobj, |
---|
| 371 | + struct bin_attribute *attr, char *buf, |
---|
| 372 | + loff_t off, size_t count) |
---|
| 373 | +{ |
---|
| 374 | + unsigned int size = ipl_block.nvme.scp_data_len; |
---|
| 375 | + void *scp_data = &ipl_block.nvme.scp_data; |
---|
| 376 | + |
---|
| 377 | + return memory_read_from_buffer(buf, count, &off, scp_data, size); |
---|
| 378 | +} |
---|
| 379 | + |
---|
416 | 380 | static struct bin_attribute ipl_scp_data_attr = |
---|
417 | 381 | __BIN_ATTR(scp_data, S_IRUGO, ipl_scp_data_read, NULL, PAGE_SIZE); |
---|
| 382 | + |
---|
| 383 | +static struct bin_attribute ipl_nvme_scp_data_attr = |
---|
| 384 | + __BIN_ATTR(scp_data, S_IRUGO, ipl_nvme_scp_data_read, NULL, PAGE_SIZE); |
---|
418 | 385 | |
---|
419 | 386 | static struct bin_attribute *ipl_fcp_bin_attrs[] = { |
---|
420 | 387 | &ipl_parameter_attr, |
---|
.. | .. |
---|
422 | 389 | NULL, |
---|
423 | 390 | }; |
---|
424 | 391 | |
---|
| 392 | +static struct bin_attribute *ipl_nvme_bin_attrs[] = { |
---|
| 393 | + &ipl_parameter_attr, |
---|
| 394 | + &ipl_nvme_scp_data_attr, |
---|
| 395 | + NULL, |
---|
| 396 | +}; |
---|
| 397 | + |
---|
425 | 398 | /* FCP ipl device attributes */ |
---|
426 | 399 | |
---|
427 | 400 | DEFINE_IPL_ATTR_RO(ipl_fcp, wwpn, "0x%016llx\n", |
---|
428 | | - (unsigned long long)ipl_block.ipl_info.fcp.wwpn); |
---|
| 401 | + (unsigned long long)ipl_block.fcp.wwpn); |
---|
429 | 402 | DEFINE_IPL_ATTR_RO(ipl_fcp, lun, "0x%016llx\n", |
---|
430 | | - (unsigned long long)ipl_block.ipl_info.fcp.lun); |
---|
| 403 | + (unsigned long long)ipl_block.fcp.lun); |
---|
431 | 404 | DEFINE_IPL_ATTR_RO(ipl_fcp, bootprog, "%lld\n", |
---|
432 | | - (unsigned long long)ipl_block.ipl_info.fcp.bootprog); |
---|
| 405 | + (unsigned long long)ipl_block.fcp.bootprog); |
---|
433 | 406 | DEFINE_IPL_ATTR_RO(ipl_fcp, br_lba, "%lld\n", |
---|
434 | | - (unsigned long long)ipl_block.ipl_info.fcp.br_lba); |
---|
| 407 | + (unsigned long long)ipl_block.fcp.br_lba); |
---|
| 408 | + |
---|
| 409 | +/* NVMe ipl device attributes */ |
---|
| 410 | +DEFINE_IPL_ATTR_RO(ipl_nvme, fid, "0x%08llx\n", |
---|
| 411 | + (unsigned long long)ipl_block.nvme.fid); |
---|
| 412 | +DEFINE_IPL_ATTR_RO(ipl_nvme, nsid, "0x%08llx\n", |
---|
| 413 | + (unsigned long long)ipl_block.nvme.nsid); |
---|
| 414 | +DEFINE_IPL_ATTR_RO(ipl_nvme, bootprog, "%lld\n", |
---|
| 415 | + (unsigned long long)ipl_block.nvme.bootprog); |
---|
| 416 | +DEFINE_IPL_ATTR_RO(ipl_nvme, br_lba, "%lld\n", |
---|
| 417 | + (unsigned long long)ipl_block.nvme.br_lba); |
---|
435 | 418 | |
---|
436 | 419 | static ssize_t ipl_ccw_loadparm_show(struct kobject *kobj, |
---|
437 | 420 | struct kobj_attribute *attr, char *page) |
---|
.. | .. |
---|
457 | 440 | &sys_ipl_fcp_bootprog_attr.attr, |
---|
458 | 441 | &sys_ipl_fcp_br_lba_attr.attr, |
---|
459 | 442 | &sys_ipl_ccw_loadparm_attr.attr, |
---|
| 443 | + &sys_ipl_secure_attr.attr, |
---|
| 444 | + &sys_ipl_has_secure_attr.attr, |
---|
460 | 445 | NULL, |
---|
461 | 446 | }; |
---|
462 | 447 | |
---|
.. | .. |
---|
465 | 450 | .bin_attrs = ipl_fcp_bin_attrs, |
---|
466 | 451 | }; |
---|
467 | 452 | |
---|
| 453 | +static struct attribute *ipl_nvme_attrs[] = { |
---|
| 454 | + &sys_ipl_type_attr.attr, |
---|
| 455 | + &sys_ipl_nvme_fid_attr.attr, |
---|
| 456 | + &sys_ipl_nvme_nsid_attr.attr, |
---|
| 457 | + &sys_ipl_nvme_bootprog_attr.attr, |
---|
| 458 | + &sys_ipl_nvme_br_lba_attr.attr, |
---|
| 459 | + &sys_ipl_ccw_loadparm_attr.attr, |
---|
| 460 | + &sys_ipl_secure_attr.attr, |
---|
| 461 | + &sys_ipl_has_secure_attr.attr, |
---|
| 462 | + NULL, |
---|
| 463 | +}; |
---|
| 464 | + |
---|
| 465 | +static struct attribute_group ipl_nvme_attr_group = { |
---|
| 466 | + .attrs = ipl_nvme_attrs, |
---|
| 467 | + .bin_attrs = ipl_nvme_bin_attrs, |
---|
| 468 | +}; |
---|
| 469 | + |
---|
| 470 | + |
---|
468 | 471 | /* CCW ipl device attributes */ |
---|
469 | 472 | |
---|
470 | 473 | static struct attribute *ipl_ccw_attrs_vm[] = { |
---|
.. | .. |
---|
472 | 475 | &sys_ipl_device_attr.attr, |
---|
473 | 476 | &sys_ipl_ccw_loadparm_attr.attr, |
---|
474 | 477 | &sys_ipl_vm_parm_attr.attr, |
---|
| 478 | + &sys_ipl_secure_attr.attr, |
---|
| 479 | + &sys_ipl_has_secure_attr.attr, |
---|
475 | 480 | NULL, |
---|
476 | 481 | }; |
---|
477 | 482 | |
---|
.. | .. |
---|
479 | 484 | &sys_ipl_type_attr.attr, |
---|
480 | 485 | &sys_ipl_device_attr.attr, |
---|
481 | 486 | &sys_ipl_ccw_loadparm_attr.attr, |
---|
| 487 | + &sys_ipl_secure_attr.attr, |
---|
| 488 | + &sys_ipl_has_secure_attr.attr, |
---|
482 | 489 | NULL, |
---|
483 | 490 | }; |
---|
484 | 491 | |
---|
.. | .. |
---|
494 | 501 | |
---|
495 | 502 | static struct attribute *ipl_unknown_attrs[] = { |
---|
496 | 503 | &sys_ipl_type_attr.attr, |
---|
| 504 | + &sys_ipl_secure_attr.attr, |
---|
| 505 | + &sys_ipl_has_secure_attr.attr, |
---|
497 | 506 | NULL, |
---|
498 | 507 | }; |
---|
499 | 508 | |
---|
.. | .. |
---|
536 | 545 | case IPL_TYPE_FCP_DUMP: |
---|
537 | 546 | rc = sysfs_create_group(&ipl_kset->kobj, &ipl_fcp_attr_group); |
---|
538 | 547 | break; |
---|
| 548 | + case IPL_TYPE_NVME: |
---|
| 549 | + case IPL_TYPE_NVME_DUMP: |
---|
| 550 | + rc = sysfs_create_group(&ipl_kset->kobj, &ipl_nvme_attr_group); |
---|
| 551 | + break; |
---|
539 | 552 | default: |
---|
540 | 553 | rc = sysfs_create_group(&ipl_kset->kobj, |
---|
541 | 554 | &ipl_unknown_attr_group); |
---|
.. | .. |
---|
564 | 577 | { |
---|
565 | 578 | char vmparm[DIAG308_VMPARM_SIZE + 1] = {}; |
---|
566 | 579 | |
---|
567 | | - reipl_get_ascii_vmparm(vmparm, sizeof(vmparm), ipb); |
---|
| 580 | + ipl_block_get_ascii_vmparm(vmparm, sizeof(vmparm), ipb); |
---|
568 | 581 | return sprintf(page, "%s\n", vmparm); |
---|
569 | 582 | } |
---|
570 | 583 | |
---|
.. | .. |
---|
587 | 600 | if (!(isalnum(buf[i]) || isascii(buf[i]) || isprint(buf[i]))) |
---|
588 | 601 | return -EINVAL; |
---|
589 | 602 | |
---|
590 | | - memset(ipb->ipl_info.ccw.vm_parm, 0, DIAG308_VMPARM_SIZE); |
---|
591 | | - ipb->ipl_info.ccw.vm_parm_len = ip_len; |
---|
| 603 | + memset(ipb->ccw.vm_parm, 0, DIAG308_VMPARM_SIZE); |
---|
| 604 | + ipb->ccw.vm_parm_len = ip_len; |
---|
592 | 605 | if (ip_len > 0) { |
---|
593 | | - ipb->ipl_info.ccw.vm_flags |= DIAG308_VM_FLAGS_VP_VALID; |
---|
594 | | - memcpy(ipb->ipl_info.ccw.vm_parm, buf, ip_len); |
---|
595 | | - ASCEBC(ipb->ipl_info.ccw.vm_parm, ip_len); |
---|
| 606 | + ipb->ccw.vm_flags |= IPL_PB0_CCW_VM_FLAG_VP; |
---|
| 607 | + memcpy(ipb->ccw.vm_parm, buf, ip_len); |
---|
| 608 | + ASCEBC(ipb->ccw.vm_parm, ip_len); |
---|
596 | 609 | } else { |
---|
597 | | - ipb->ipl_info.ccw.vm_flags &= ~DIAG308_VM_FLAGS_VP_VALID; |
---|
| 610 | + ipb->ccw.vm_flags &= ~IPL_PB0_CCW_VM_FLAG_VP; |
---|
598 | 611 | } |
---|
599 | 612 | |
---|
600 | 613 | return len; |
---|
.. | .. |
---|
641 | 654 | struct bin_attribute *attr, |
---|
642 | 655 | char *buf, loff_t off, size_t count) |
---|
643 | 656 | { |
---|
644 | | - size_t size = reipl_block_fcp->ipl_info.fcp.scp_data_len; |
---|
645 | | - void *scp_data = reipl_block_fcp->ipl_info.fcp.scp_data; |
---|
| 657 | + size_t size = reipl_block_fcp->fcp.scp_data_len; |
---|
| 658 | + void *scp_data = reipl_block_fcp->fcp.scp_data; |
---|
646 | 659 | |
---|
647 | 660 | return memory_read_from_buffer(buf, count, &off, scp_data, size); |
---|
648 | 661 | } |
---|
.. | .. |
---|
658 | 671 | if (off) |
---|
659 | 672 | return -EINVAL; |
---|
660 | 673 | |
---|
661 | | - memcpy(reipl_block_fcp->ipl_info.fcp.scp_data, buf, count); |
---|
| 674 | + memcpy(reipl_block_fcp->fcp.scp_data, buf, count); |
---|
662 | 675 | if (scpdata_len % 8) { |
---|
663 | 676 | padding = 8 - (scpdata_len % 8); |
---|
664 | | - memset(reipl_block_fcp->ipl_info.fcp.scp_data + scpdata_len, |
---|
| 677 | + memset(reipl_block_fcp->fcp.scp_data + scpdata_len, |
---|
665 | 678 | 0, padding); |
---|
666 | 679 | scpdata_len += padding; |
---|
667 | 680 | } |
---|
668 | 681 | |
---|
669 | | - reipl_block_fcp->ipl_info.fcp.scp_data_len = scpdata_len; |
---|
670 | | - reipl_block_fcp->hdr.len = IPL_PARM_BLK_FCP_LEN + scpdata_len; |
---|
671 | | - reipl_block_fcp->hdr.blk0_len = IPL_PARM_BLK0_FCP_LEN + scpdata_len; |
---|
| 682 | + reipl_block_fcp->hdr.len = IPL_BP_FCP_LEN + scpdata_len; |
---|
| 683 | + reipl_block_fcp->fcp.len = IPL_BP0_FCP_LEN + scpdata_len; |
---|
| 684 | + reipl_block_fcp->fcp.scp_data_len = scpdata_len; |
---|
672 | 685 | |
---|
673 | 686 | return count; |
---|
674 | 687 | } |
---|
.. | .. |
---|
682 | 695 | }; |
---|
683 | 696 | |
---|
684 | 697 | DEFINE_IPL_ATTR_RW(reipl_fcp, wwpn, "0x%016llx\n", "%llx\n", |
---|
685 | | - reipl_block_fcp->ipl_info.fcp.wwpn); |
---|
| 698 | + reipl_block_fcp->fcp.wwpn); |
---|
686 | 699 | DEFINE_IPL_ATTR_RW(reipl_fcp, lun, "0x%016llx\n", "%llx\n", |
---|
687 | | - reipl_block_fcp->ipl_info.fcp.lun); |
---|
| 700 | + reipl_block_fcp->fcp.lun); |
---|
688 | 701 | DEFINE_IPL_ATTR_RW(reipl_fcp, bootprog, "%lld\n", "%lld\n", |
---|
689 | | - reipl_block_fcp->ipl_info.fcp.bootprog); |
---|
| 702 | + reipl_block_fcp->fcp.bootprog); |
---|
690 | 703 | DEFINE_IPL_ATTR_RW(reipl_fcp, br_lba, "%lld\n", "%lld\n", |
---|
691 | | - reipl_block_fcp->ipl_info.fcp.br_lba); |
---|
| 704 | + reipl_block_fcp->fcp.br_lba); |
---|
692 | 705 | DEFINE_IPL_ATTR_RW(reipl_fcp, device, "0.0.%04llx\n", "0.0.%llx\n", |
---|
693 | | - reipl_block_fcp->ipl_info.fcp.devno); |
---|
| 706 | + reipl_block_fcp->fcp.devno); |
---|
694 | 707 | |
---|
695 | 708 | static void reipl_get_ascii_loadparm(char *loadparm, |
---|
696 | 709 | struct ipl_parameter_block *ibp) |
---|
697 | 710 | { |
---|
698 | | - memcpy(loadparm, ibp->hdr.loadparm, LOADPARM_LEN); |
---|
| 711 | + memcpy(loadparm, ibp->common.loadparm, LOADPARM_LEN); |
---|
699 | 712 | EBCASC(loadparm, LOADPARM_LEN); |
---|
700 | 713 | loadparm[LOADPARM_LEN] = 0; |
---|
701 | 714 | strim(loadparm); |
---|
.. | .. |
---|
730 | 743 | return -EINVAL; |
---|
731 | 744 | } |
---|
732 | 745 | /* initialize loadparm with blanks */ |
---|
733 | | - memset(ipb->hdr.loadparm, ' ', LOADPARM_LEN); |
---|
| 746 | + memset(ipb->common.loadparm, ' ', LOADPARM_LEN); |
---|
734 | 747 | /* copy and convert to ebcdic */ |
---|
735 | | - memcpy(ipb->hdr.loadparm, buf, lp_len); |
---|
736 | | - ASCEBC(ipb->hdr.loadparm, LOADPARM_LEN); |
---|
737 | | - ipb->hdr.flags |= DIAG308_FLAGS_LP_VALID; |
---|
| 748 | + memcpy(ipb->common.loadparm, buf, lp_len); |
---|
| 749 | + ASCEBC(ipb->common.loadparm, LOADPARM_LEN); |
---|
| 750 | + ipb->common.flags |= IPL_PB0_FLAG_LOADPARM; |
---|
738 | 751 | return len; |
---|
739 | 752 | } |
---|
740 | 753 | |
---|
.. | .. |
---|
756 | 769 | __ATTR(loadparm, S_IRUGO | S_IWUSR, reipl_fcp_loadparm_show, |
---|
757 | 770 | reipl_fcp_loadparm_store); |
---|
758 | 771 | |
---|
| 772 | +static ssize_t reipl_fcp_clear_show(struct kobject *kobj, |
---|
| 773 | + struct kobj_attribute *attr, char *page) |
---|
| 774 | +{ |
---|
| 775 | + return sprintf(page, "%u\n", reipl_fcp_clear); |
---|
| 776 | +} |
---|
| 777 | + |
---|
| 778 | +static ssize_t reipl_fcp_clear_store(struct kobject *kobj, |
---|
| 779 | + struct kobj_attribute *attr, |
---|
| 780 | + const char *buf, size_t len) |
---|
| 781 | +{ |
---|
| 782 | + if (strtobool(buf, &reipl_fcp_clear) < 0) |
---|
| 783 | + return -EINVAL; |
---|
| 784 | + return len; |
---|
| 785 | +} |
---|
| 786 | + |
---|
759 | 787 | static struct attribute *reipl_fcp_attrs[] = { |
---|
760 | 788 | &sys_reipl_fcp_device_attr.attr, |
---|
761 | 789 | &sys_reipl_fcp_wwpn_attr.attr, |
---|
.. | .. |
---|
771 | 799 | .bin_attrs = reipl_fcp_bin_attrs, |
---|
772 | 800 | }; |
---|
773 | 801 | |
---|
| 802 | +static struct kobj_attribute sys_reipl_fcp_clear_attr = |
---|
| 803 | + __ATTR(clear, 0644, reipl_fcp_clear_show, reipl_fcp_clear_store); |
---|
| 804 | + |
---|
| 805 | +/* NVME reipl device attributes */ |
---|
| 806 | + |
---|
| 807 | +static ssize_t reipl_nvme_scpdata_read(struct file *filp, struct kobject *kobj, |
---|
| 808 | + struct bin_attribute *attr, |
---|
| 809 | + char *buf, loff_t off, size_t count) |
---|
| 810 | +{ |
---|
| 811 | + size_t size = reipl_block_nvme->nvme.scp_data_len; |
---|
| 812 | + void *scp_data = reipl_block_nvme->nvme.scp_data; |
---|
| 813 | + |
---|
| 814 | + return memory_read_from_buffer(buf, count, &off, scp_data, size); |
---|
| 815 | +} |
---|
| 816 | + |
---|
| 817 | +static ssize_t reipl_nvme_scpdata_write(struct file *filp, struct kobject *kobj, |
---|
| 818 | + struct bin_attribute *attr, |
---|
| 819 | + char *buf, loff_t off, size_t count) |
---|
| 820 | +{ |
---|
| 821 | + size_t scpdata_len = count; |
---|
| 822 | + size_t padding; |
---|
| 823 | + |
---|
| 824 | + if (off) |
---|
| 825 | + return -EINVAL; |
---|
| 826 | + |
---|
| 827 | + memcpy(reipl_block_nvme->nvme.scp_data, buf, count); |
---|
| 828 | + if (scpdata_len % 8) { |
---|
| 829 | + padding = 8 - (scpdata_len % 8); |
---|
| 830 | + memset(reipl_block_nvme->nvme.scp_data + scpdata_len, |
---|
| 831 | + 0, padding); |
---|
| 832 | + scpdata_len += padding; |
---|
| 833 | + } |
---|
| 834 | + |
---|
| 835 | + reipl_block_nvme->hdr.len = IPL_BP_FCP_LEN + scpdata_len; |
---|
| 836 | + reipl_block_nvme->nvme.len = IPL_BP0_FCP_LEN + scpdata_len; |
---|
| 837 | + reipl_block_nvme->nvme.scp_data_len = scpdata_len; |
---|
| 838 | + |
---|
| 839 | + return count; |
---|
| 840 | +} |
---|
| 841 | + |
---|
| 842 | +static struct bin_attribute sys_reipl_nvme_scp_data_attr = |
---|
| 843 | + __BIN_ATTR(scp_data, (S_IRUGO | S_IWUSR), reipl_nvme_scpdata_read, |
---|
| 844 | + reipl_nvme_scpdata_write, DIAG308_SCPDATA_SIZE); |
---|
| 845 | + |
---|
| 846 | +static struct bin_attribute *reipl_nvme_bin_attrs[] = { |
---|
| 847 | + &sys_reipl_nvme_scp_data_attr, |
---|
| 848 | + NULL, |
---|
| 849 | +}; |
---|
| 850 | + |
---|
| 851 | +DEFINE_IPL_ATTR_RW(reipl_nvme, fid, "0x%08llx\n", "%llx\n", |
---|
| 852 | + reipl_block_nvme->nvme.fid); |
---|
| 853 | +DEFINE_IPL_ATTR_RW(reipl_nvme, nsid, "0x%08llx\n", "%llx\n", |
---|
| 854 | + reipl_block_nvme->nvme.nsid); |
---|
| 855 | +DEFINE_IPL_ATTR_RW(reipl_nvme, bootprog, "%lld\n", "%lld\n", |
---|
| 856 | + reipl_block_nvme->nvme.bootprog); |
---|
| 857 | +DEFINE_IPL_ATTR_RW(reipl_nvme, br_lba, "%lld\n", "%lld\n", |
---|
| 858 | + reipl_block_nvme->nvme.br_lba); |
---|
| 859 | + |
---|
| 860 | +/* nvme wrapper */ |
---|
| 861 | +static ssize_t reipl_nvme_loadparm_show(struct kobject *kobj, |
---|
| 862 | + struct kobj_attribute *attr, char *page) |
---|
| 863 | +{ |
---|
| 864 | + return reipl_generic_loadparm_show(reipl_block_nvme, page); |
---|
| 865 | +} |
---|
| 866 | + |
---|
| 867 | +static ssize_t reipl_nvme_loadparm_store(struct kobject *kobj, |
---|
| 868 | + struct kobj_attribute *attr, |
---|
| 869 | + const char *buf, size_t len) |
---|
| 870 | +{ |
---|
| 871 | + return reipl_generic_loadparm_store(reipl_block_nvme, buf, len); |
---|
| 872 | +} |
---|
| 873 | + |
---|
| 874 | +static struct kobj_attribute sys_reipl_nvme_loadparm_attr = |
---|
| 875 | + __ATTR(loadparm, S_IRUGO | S_IWUSR, reipl_nvme_loadparm_show, |
---|
| 876 | + reipl_nvme_loadparm_store); |
---|
| 877 | + |
---|
| 878 | +static struct attribute *reipl_nvme_attrs[] = { |
---|
| 879 | + &sys_reipl_nvme_fid_attr.attr, |
---|
| 880 | + &sys_reipl_nvme_nsid_attr.attr, |
---|
| 881 | + &sys_reipl_nvme_bootprog_attr.attr, |
---|
| 882 | + &sys_reipl_nvme_br_lba_attr.attr, |
---|
| 883 | + &sys_reipl_nvme_loadparm_attr.attr, |
---|
| 884 | + NULL, |
---|
| 885 | +}; |
---|
| 886 | + |
---|
| 887 | +static struct attribute_group reipl_nvme_attr_group = { |
---|
| 888 | + .attrs = reipl_nvme_attrs, |
---|
| 889 | + .bin_attrs = reipl_nvme_bin_attrs |
---|
| 890 | +}; |
---|
| 891 | + |
---|
| 892 | +static ssize_t reipl_nvme_clear_show(struct kobject *kobj, |
---|
| 893 | + struct kobj_attribute *attr, char *page) |
---|
| 894 | +{ |
---|
| 895 | + return sprintf(page, "%u\n", reipl_nvme_clear); |
---|
| 896 | +} |
---|
| 897 | + |
---|
| 898 | +static ssize_t reipl_nvme_clear_store(struct kobject *kobj, |
---|
| 899 | + struct kobj_attribute *attr, |
---|
| 900 | + const char *buf, size_t len) |
---|
| 901 | +{ |
---|
| 902 | + if (strtobool(buf, &reipl_nvme_clear) < 0) |
---|
| 903 | + return -EINVAL; |
---|
| 904 | + return len; |
---|
| 905 | +} |
---|
| 906 | + |
---|
| 907 | +static struct kobj_attribute sys_reipl_nvme_clear_attr = |
---|
| 908 | + __ATTR(clear, 0644, reipl_nvme_clear_show, reipl_nvme_clear_store); |
---|
| 909 | + |
---|
774 | 910 | /* CCW reipl device attributes */ |
---|
775 | | -DEFINE_IPL_CCW_ATTR_RW(reipl_ccw, device, reipl_block_ccw->ipl_info.ccw); |
---|
| 911 | +DEFINE_IPL_CCW_ATTR_RW(reipl_ccw, device, reipl_block_ccw->ccw); |
---|
776 | 912 | |
---|
777 | 913 | /* NSS wrapper */ |
---|
778 | 914 | static ssize_t reipl_nss_loadparm_show(struct kobject *kobj, |
---|
.. | .. |
---|
806 | 942 | __ATTR(loadparm, S_IRUGO | S_IWUSR, reipl_ccw_loadparm_show, |
---|
807 | 943 | reipl_ccw_loadparm_store); |
---|
808 | 944 | |
---|
| 945 | +static ssize_t reipl_ccw_clear_show(struct kobject *kobj, |
---|
| 946 | + struct kobj_attribute *attr, char *page) |
---|
| 947 | +{ |
---|
| 948 | + return sprintf(page, "%u\n", reipl_ccw_clear); |
---|
| 949 | +} |
---|
| 950 | + |
---|
| 951 | +static ssize_t reipl_ccw_clear_store(struct kobject *kobj, |
---|
| 952 | + struct kobj_attribute *attr, |
---|
| 953 | + const char *buf, size_t len) |
---|
| 954 | +{ |
---|
| 955 | + if (strtobool(buf, &reipl_ccw_clear) < 0) |
---|
| 956 | + return -EINVAL; |
---|
| 957 | + return len; |
---|
| 958 | +} |
---|
| 959 | + |
---|
| 960 | +static struct kobj_attribute sys_reipl_ccw_clear_attr = |
---|
| 961 | + __ATTR(clear, 0644, reipl_ccw_clear_show, reipl_ccw_clear_store); |
---|
| 962 | + |
---|
809 | 963 | static struct attribute *reipl_ccw_attrs_vm[] = { |
---|
810 | 964 | &sys_reipl_ccw_device_attr.attr, |
---|
811 | 965 | &sys_reipl_ccw_loadparm_attr.attr, |
---|
812 | 966 | &sys_reipl_ccw_vmparm_attr.attr, |
---|
| 967 | + &sys_reipl_ccw_clear_attr.attr, |
---|
813 | 968 | NULL, |
---|
814 | 969 | }; |
---|
815 | 970 | |
---|
816 | 971 | static struct attribute *reipl_ccw_attrs_lpar[] = { |
---|
817 | 972 | &sys_reipl_ccw_device_attr.attr, |
---|
818 | 973 | &sys_reipl_ccw_loadparm_attr.attr, |
---|
| 974 | + &sys_reipl_ccw_clear_attr.attr, |
---|
819 | 975 | NULL, |
---|
820 | 976 | }; |
---|
821 | 977 | |
---|
.. | .. |
---|
834 | 990 | static void reipl_get_ascii_nss_name(char *dst, |
---|
835 | 991 | struct ipl_parameter_block *ipb) |
---|
836 | 992 | { |
---|
837 | | - memcpy(dst, ipb->ipl_info.ccw.nss_name, NSS_NAME_SIZE); |
---|
| 993 | + memcpy(dst, ipb->ccw.nss_name, NSS_NAME_SIZE); |
---|
838 | 994 | EBCASC(dst, NSS_NAME_SIZE); |
---|
839 | 995 | dst[NSS_NAME_SIZE] = 0; |
---|
840 | 996 | } |
---|
.. | .. |
---|
862 | 1018 | if (nss_len > NSS_NAME_SIZE) |
---|
863 | 1019 | return -EINVAL; |
---|
864 | 1020 | |
---|
865 | | - memset(reipl_block_nss->ipl_info.ccw.nss_name, 0x40, NSS_NAME_SIZE); |
---|
| 1021 | + memset(reipl_block_nss->ccw.nss_name, 0x40, NSS_NAME_SIZE); |
---|
866 | 1022 | if (nss_len > 0) { |
---|
867 | | - reipl_block_nss->ipl_info.ccw.vm_flags |= |
---|
868 | | - DIAG308_VM_FLAGS_NSS_VALID; |
---|
869 | | - memcpy(reipl_block_nss->ipl_info.ccw.nss_name, buf, nss_len); |
---|
870 | | - ASCEBC(reipl_block_nss->ipl_info.ccw.nss_name, nss_len); |
---|
871 | | - EBC_TOUPPER(reipl_block_nss->ipl_info.ccw.nss_name, nss_len); |
---|
| 1023 | + reipl_block_nss->ccw.vm_flags |= IPL_PB0_CCW_VM_FLAG_NSS; |
---|
| 1024 | + memcpy(reipl_block_nss->ccw.nss_name, buf, nss_len); |
---|
| 1025 | + ASCEBC(reipl_block_nss->ccw.nss_name, nss_len); |
---|
| 1026 | + EBC_TOUPPER(reipl_block_nss->ccw.nss_name, nss_len); |
---|
872 | 1027 | } else { |
---|
873 | | - reipl_block_nss->ipl_info.ccw.vm_flags &= |
---|
874 | | - ~DIAG308_VM_FLAGS_NSS_VALID; |
---|
| 1028 | + reipl_block_nss->ccw.vm_flags &= ~IPL_PB0_CCW_VM_FLAG_NSS; |
---|
875 | 1029 | } |
---|
876 | 1030 | |
---|
877 | 1031 | return len; |
---|
.. | .. |
---|
917 | 1071 | case IPL_TYPE_FCP: |
---|
918 | 1072 | reipl_block_actual = reipl_block_fcp; |
---|
919 | 1073 | break; |
---|
| 1074 | + case IPL_TYPE_NVME: |
---|
| 1075 | + reipl_block_actual = reipl_block_nvme; |
---|
| 1076 | + break; |
---|
920 | 1077 | case IPL_TYPE_NSS: |
---|
921 | 1078 | reipl_block_actual = reipl_block_nss; |
---|
922 | 1079 | break; |
---|
.. | .. |
---|
943 | 1100 | rc = reipl_set_type(IPL_TYPE_CCW); |
---|
944 | 1101 | else if (strncmp(buf, IPL_FCP_STR, strlen(IPL_FCP_STR)) == 0) |
---|
945 | 1102 | rc = reipl_set_type(IPL_TYPE_FCP); |
---|
| 1103 | + else if (strncmp(buf, IPL_NVME_STR, strlen(IPL_NVME_STR)) == 0) |
---|
| 1104 | + rc = reipl_set_type(IPL_TYPE_NVME); |
---|
946 | 1105 | else if (strncmp(buf, IPL_NSS_STR, strlen(IPL_NSS_STR)) == 0) |
---|
947 | 1106 | rc = reipl_set_type(IPL_TYPE_NSS); |
---|
948 | 1107 | return (rc != 0) ? rc : len; |
---|
.. | .. |
---|
953 | 1112 | |
---|
954 | 1113 | static struct kset *reipl_kset; |
---|
955 | 1114 | static struct kset *reipl_fcp_kset; |
---|
| 1115 | +static struct kset *reipl_nvme_kset; |
---|
956 | 1116 | |
---|
957 | 1117 | static void __reipl_run(void *unused) |
---|
958 | 1118 | { |
---|
959 | 1119 | switch (reipl_type) { |
---|
960 | 1120 | case IPL_TYPE_CCW: |
---|
961 | 1121 | diag308(DIAG308_SET, reipl_block_ccw); |
---|
962 | | - diag308(DIAG308_LOAD_CLEAR, NULL); |
---|
| 1122 | + if (reipl_ccw_clear) |
---|
| 1123 | + diag308(DIAG308_LOAD_CLEAR, NULL); |
---|
| 1124 | + else |
---|
| 1125 | + diag308(DIAG308_LOAD_NORMAL_DUMP, NULL); |
---|
963 | 1126 | break; |
---|
964 | 1127 | case IPL_TYPE_FCP: |
---|
965 | 1128 | diag308(DIAG308_SET, reipl_block_fcp); |
---|
966 | | - diag308(DIAG308_LOAD_CLEAR, NULL); |
---|
| 1129 | + if (reipl_fcp_clear) |
---|
| 1130 | + diag308(DIAG308_LOAD_CLEAR, NULL); |
---|
| 1131 | + else |
---|
| 1132 | + diag308(DIAG308_LOAD_NORMAL, NULL); |
---|
| 1133 | + break; |
---|
| 1134 | + case IPL_TYPE_NVME: |
---|
| 1135 | + diag308(DIAG308_SET, reipl_block_nvme); |
---|
| 1136 | + if (reipl_nvme_clear) |
---|
| 1137 | + diag308(DIAG308_LOAD_CLEAR, NULL); |
---|
| 1138 | + else |
---|
| 1139 | + diag308(DIAG308_LOAD_NORMAL, NULL); |
---|
967 | 1140 | break; |
---|
968 | 1141 | case IPL_TYPE_NSS: |
---|
969 | 1142 | diag308(DIAG308_SET, reipl_block_nss); |
---|
.. | .. |
---|
973 | 1146 | diag308(DIAG308_LOAD_CLEAR, NULL); |
---|
974 | 1147 | break; |
---|
975 | 1148 | case IPL_TYPE_FCP_DUMP: |
---|
| 1149 | + case IPL_TYPE_NVME_DUMP: |
---|
976 | 1150 | break; |
---|
977 | 1151 | } |
---|
978 | | - disabled_wait((unsigned long) __builtin_return_address(0)); |
---|
| 1152 | + disabled_wait(); |
---|
979 | 1153 | } |
---|
980 | 1154 | |
---|
981 | 1155 | static void reipl_run(struct shutdown_trigger *trigger) |
---|
.. | .. |
---|
985 | 1159 | |
---|
986 | 1160 | static void reipl_block_ccw_init(struct ipl_parameter_block *ipb) |
---|
987 | 1161 | { |
---|
988 | | - ipb->hdr.len = IPL_PARM_BLK_CCW_LEN; |
---|
| 1162 | + ipb->hdr.len = IPL_BP_CCW_LEN; |
---|
989 | 1163 | ipb->hdr.version = IPL_PARM_BLOCK_VERSION; |
---|
990 | | - ipb->hdr.blk0_len = IPL_PARM_BLK0_CCW_LEN; |
---|
991 | | - ipb->hdr.pbt = DIAG308_IPL_TYPE_CCW; |
---|
| 1164 | + ipb->pb0_hdr.len = IPL_BP0_CCW_LEN; |
---|
| 1165 | + ipb->pb0_hdr.pbt = IPL_PBT_CCW; |
---|
992 | 1166 | } |
---|
993 | 1167 | |
---|
994 | 1168 | static void reipl_block_ccw_fill_parms(struct ipl_parameter_block *ipb) |
---|
.. | .. |
---|
996 | 1170 | /* LOADPARM */ |
---|
997 | 1171 | /* check if read scp info worked and set loadparm */ |
---|
998 | 1172 | if (sclp_ipl_info.is_valid) |
---|
999 | | - memcpy(ipb->hdr.loadparm, &sclp_ipl_info.loadparm, LOADPARM_LEN); |
---|
| 1173 | + memcpy(ipb->ccw.loadparm, &sclp_ipl_info.loadparm, LOADPARM_LEN); |
---|
1000 | 1174 | else |
---|
1001 | 1175 | /* read scp info failed: set empty loadparm (EBCDIC blanks) */ |
---|
1002 | | - memset(ipb->hdr.loadparm, 0x40, LOADPARM_LEN); |
---|
1003 | | - ipb->hdr.flags = DIAG308_FLAGS_LP_VALID; |
---|
| 1176 | + memset(ipb->ccw.loadparm, 0x40, LOADPARM_LEN); |
---|
| 1177 | + ipb->ccw.flags = IPL_PB0_FLAG_LOADPARM; |
---|
1004 | 1178 | |
---|
1005 | 1179 | /* VM PARM */ |
---|
1006 | 1180 | if (MACHINE_IS_VM && ipl_block_valid && |
---|
1007 | | - (ipl_block.ipl_info.ccw.vm_flags & DIAG308_VM_FLAGS_VP_VALID)) { |
---|
| 1181 | + (ipl_block.ccw.vm_flags & IPL_PB0_CCW_VM_FLAG_VP)) { |
---|
1008 | 1182 | |
---|
1009 | | - ipb->ipl_info.ccw.vm_flags |= DIAG308_VM_FLAGS_VP_VALID; |
---|
1010 | | - ipb->ipl_info.ccw.vm_parm_len = |
---|
1011 | | - ipl_block.ipl_info.ccw.vm_parm_len; |
---|
1012 | | - memcpy(ipb->ipl_info.ccw.vm_parm, |
---|
1013 | | - ipl_block.ipl_info.ccw.vm_parm, DIAG308_VMPARM_SIZE); |
---|
| 1183 | + ipb->ccw.vm_flags |= IPL_PB0_CCW_VM_FLAG_VP; |
---|
| 1184 | + ipb->ccw.vm_parm_len = ipl_block.ccw.vm_parm_len; |
---|
| 1185 | + memcpy(ipb->ccw.vm_parm, |
---|
| 1186 | + ipl_block.ccw.vm_parm, DIAG308_VMPARM_SIZE); |
---|
1014 | 1187 | } |
---|
1015 | 1188 | } |
---|
1016 | 1189 | |
---|
.. | .. |
---|
1050 | 1223 | |
---|
1051 | 1224 | reipl_block_ccw_init(reipl_block_ccw); |
---|
1052 | 1225 | if (ipl_info.type == IPL_TYPE_CCW) { |
---|
1053 | | - reipl_block_ccw->ipl_info.ccw.ssid = ipl_block.ipl_info.ccw.ssid; |
---|
1054 | | - reipl_block_ccw->ipl_info.ccw.devno = ipl_block.ipl_info.ccw.devno; |
---|
| 1226 | + reipl_block_ccw->ccw.ssid = ipl_block.ccw.ssid; |
---|
| 1227 | + reipl_block_ccw->ccw.devno = ipl_block.ccw.devno; |
---|
1055 | 1228 | reipl_block_ccw_fill_parms(reipl_block_ccw); |
---|
1056 | 1229 | } |
---|
1057 | 1230 | |
---|
.. | .. |
---|
1076 | 1249 | } |
---|
1077 | 1250 | |
---|
1078 | 1251 | rc = sysfs_create_group(&reipl_fcp_kset->kobj, &reipl_fcp_attr_group); |
---|
1079 | | - if (rc) { |
---|
1080 | | - kset_unregister(reipl_fcp_kset); |
---|
1081 | | - free_page((unsigned long) reipl_block_fcp); |
---|
1082 | | - return rc; |
---|
| 1252 | + if (rc) |
---|
| 1253 | + goto out1; |
---|
| 1254 | + |
---|
| 1255 | + if (test_facility(141)) { |
---|
| 1256 | + rc = sysfs_create_file(&reipl_fcp_kset->kobj, |
---|
| 1257 | + &sys_reipl_fcp_clear_attr.attr); |
---|
| 1258 | + if (rc) |
---|
| 1259 | + goto out2; |
---|
| 1260 | + } else { |
---|
| 1261 | + reipl_fcp_clear = true; |
---|
1083 | 1262 | } |
---|
1084 | 1263 | |
---|
1085 | 1264 | if (ipl_info.type == IPL_TYPE_FCP) { |
---|
.. | .. |
---|
1089 | 1268 | * is invalid in the SCSI IPL parameter block, so take it |
---|
1090 | 1269 | * always from sclp_ipl_info. |
---|
1091 | 1270 | */ |
---|
1092 | | - memcpy(reipl_block_fcp->hdr.loadparm, sclp_ipl_info.loadparm, |
---|
| 1271 | + memcpy(reipl_block_fcp->fcp.loadparm, sclp_ipl_info.loadparm, |
---|
1093 | 1272 | LOADPARM_LEN); |
---|
1094 | 1273 | } else { |
---|
1095 | | - reipl_block_fcp->hdr.len = IPL_PARM_BLK_FCP_LEN; |
---|
| 1274 | + reipl_block_fcp->hdr.len = IPL_BP_FCP_LEN; |
---|
1096 | 1275 | reipl_block_fcp->hdr.version = IPL_PARM_BLOCK_VERSION; |
---|
1097 | | - reipl_block_fcp->hdr.blk0_len = IPL_PARM_BLK0_FCP_LEN; |
---|
1098 | | - reipl_block_fcp->hdr.pbt = DIAG308_IPL_TYPE_FCP; |
---|
1099 | | - reipl_block_fcp->ipl_info.fcp.opt = DIAG308_IPL_OPT_IPL; |
---|
| 1276 | + reipl_block_fcp->fcp.len = IPL_BP0_FCP_LEN; |
---|
| 1277 | + reipl_block_fcp->fcp.pbt = IPL_PBT_FCP; |
---|
| 1278 | + reipl_block_fcp->fcp.opt = IPL_PB0_FCP_OPT_IPL; |
---|
1100 | 1279 | } |
---|
1101 | 1280 | reipl_capabilities |= IPL_TYPE_FCP; |
---|
1102 | 1281 | return 0; |
---|
| 1282 | + |
---|
| 1283 | +out2: |
---|
| 1284 | + sysfs_remove_group(&reipl_fcp_kset->kobj, &reipl_fcp_attr_group); |
---|
| 1285 | +out1: |
---|
| 1286 | + kset_unregister(reipl_fcp_kset); |
---|
| 1287 | + free_page((unsigned long) reipl_block_fcp); |
---|
| 1288 | + return rc; |
---|
| 1289 | +} |
---|
| 1290 | + |
---|
| 1291 | +static int __init reipl_nvme_init(void) |
---|
| 1292 | +{ |
---|
| 1293 | + int rc; |
---|
| 1294 | + |
---|
| 1295 | + reipl_block_nvme = (void *) get_zeroed_page(GFP_KERNEL); |
---|
| 1296 | + if (!reipl_block_nvme) |
---|
| 1297 | + return -ENOMEM; |
---|
| 1298 | + |
---|
| 1299 | + /* sysfs: create kset for mixing attr group and bin attrs */ |
---|
| 1300 | + reipl_nvme_kset = kset_create_and_add(IPL_NVME_STR, NULL, |
---|
| 1301 | + &reipl_kset->kobj); |
---|
| 1302 | + if (!reipl_nvme_kset) { |
---|
| 1303 | + free_page((unsigned long) reipl_block_nvme); |
---|
| 1304 | + return -ENOMEM; |
---|
| 1305 | + } |
---|
| 1306 | + |
---|
| 1307 | + rc = sysfs_create_group(&reipl_nvme_kset->kobj, &reipl_nvme_attr_group); |
---|
| 1308 | + if (rc) |
---|
| 1309 | + goto out1; |
---|
| 1310 | + |
---|
| 1311 | + if (test_facility(141)) { |
---|
| 1312 | + rc = sysfs_create_file(&reipl_nvme_kset->kobj, |
---|
| 1313 | + &sys_reipl_nvme_clear_attr.attr); |
---|
| 1314 | + if (rc) |
---|
| 1315 | + goto out2; |
---|
| 1316 | + } else { |
---|
| 1317 | + reipl_nvme_clear = true; |
---|
| 1318 | + } |
---|
| 1319 | + |
---|
| 1320 | + if (ipl_info.type == IPL_TYPE_NVME) { |
---|
| 1321 | + memcpy(reipl_block_nvme, &ipl_block, sizeof(ipl_block)); |
---|
| 1322 | + /* |
---|
| 1323 | + * Fix loadparm: There are systems where the (SCSI) LOADPARM |
---|
| 1324 | + * is invalid in the IPL parameter block, so take it |
---|
| 1325 | + * always from sclp_ipl_info. |
---|
| 1326 | + */ |
---|
| 1327 | + memcpy(reipl_block_nvme->nvme.loadparm, sclp_ipl_info.loadparm, |
---|
| 1328 | + LOADPARM_LEN); |
---|
| 1329 | + } else { |
---|
| 1330 | + reipl_block_nvme->hdr.len = IPL_BP_NVME_LEN; |
---|
| 1331 | + reipl_block_nvme->hdr.version = IPL_PARM_BLOCK_VERSION; |
---|
| 1332 | + reipl_block_nvme->nvme.len = IPL_BP0_NVME_LEN; |
---|
| 1333 | + reipl_block_nvme->nvme.pbt = IPL_PBT_NVME; |
---|
| 1334 | + reipl_block_nvme->nvme.opt = IPL_PB0_NVME_OPT_IPL; |
---|
| 1335 | + } |
---|
| 1336 | + reipl_capabilities |= IPL_TYPE_NVME; |
---|
| 1337 | + return 0; |
---|
| 1338 | + |
---|
| 1339 | +out2: |
---|
| 1340 | + sysfs_remove_group(&reipl_nvme_kset->kobj, &reipl_nvme_attr_group); |
---|
| 1341 | +out1: |
---|
| 1342 | + kset_unregister(reipl_nvme_kset); |
---|
| 1343 | + free_page((unsigned long) reipl_block_nvme); |
---|
| 1344 | + return rc; |
---|
1103 | 1345 | } |
---|
1104 | 1346 | |
---|
1105 | 1347 | static int __init reipl_type_init(void) |
---|
.. | .. |
---|
1114 | 1356 | /* |
---|
1115 | 1357 | * If we have an OS info reipl block, this will be used |
---|
1116 | 1358 | */ |
---|
1117 | | - if (reipl_block->hdr.pbt == DIAG308_IPL_TYPE_FCP) { |
---|
| 1359 | + if (reipl_block->pb0_hdr.pbt == IPL_PBT_FCP) { |
---|
1118 | 1360 | memcpy(reipl_block_fcp, reipl_block, size); |
---|
1119 | 1361 | reipl_type = IPL_TYPE_FCP; |
---|
1120 | | - } else if (reipl_block->hdr.pbt == DIAG308_IPL_TYPE_CCW) { |
---|
| 1362 | + } else if (reipl_block->pb0_hdr.pbt == IPL_PBT_NVME) { |
---|
| 1363 | + memcpy(reipl_block_nvme, reipl_block, size); |
---|
| 1364 | + reipl_type = IPL_TYPE_NVME; |
---|
| 1365 | + } else if (reipl_block->pb0_hdr.pbt == IPL_PBT_CCW) { |
---|
1121 | 1366 | memcpy(reipl_block_ccw, reipl_block, size); |
---|
1122 | 1367 | reipl_type = IPL_TYPE_CCW; |
---|
1123 | 1368 | } |
---|
.. | .. |
---|
1143 | 1388 | rc = reipl_fcp_init(); |
---|
1144 | 1389 | if (rc) |
---|
1145 | 1390 | return rc; |
---|
| 1391 | + rc = reipl_nvme_init(); |
---|
| 1392 | + if (rc) |
---|
| 1393 | + return rc; |
---|
1146 | 1394 | rc = reipl_nss_init(); |
---|
1147 | 1395 | if (rc) |
---|
1148 | 1396 | return rc; |
---|
.. | .. |
---|
1162 | 1410 | /* FCP dump device attributes */ |
---|
1163 | 1411 | |
---|
1164 | 1412 | DEFINE_IPL_ATTR_RW(dump_fcp, wwpn, "0x%016llx\n", "%llx\n", |
---|
1165 | | - dump_block_fcp->ipl_info.fcp.wwpn); |
---|
| 1413 | + dump_block_fcp->fcp.wwpn); |
---|
1166 | 1414 | DEFINE_IPL_ATTR_RW(dump_fcp, lun, "0x%016llx\n", "%llx\n", |
---|
1167 | | - dump_block_fcp->ipl_info.fcp.lun); |
---|
| 1415 | + dump_block_fcp->fcp.lun); |
---|
1168 | 1416 | DEFINE_IPL_ATTR_RW(dump_fcp, bootprog, "%lld\n", "%lld\n", |
---|
1169 | | - dump_block_fcp->ipl_info.fcp.bootprog); |
---|
| 1417 | + dump_block_fcp->fcp.bootprog); |
---|
1170 | 1418 | DEFINE_IPL_ATTR_RW(dump_fcp, br_lba, "%lld\n", "%lld\n", |
---|
1171 | | - dump_block_fcp->ipl_info.fcp.br_lba); |
---|
| 1419 | + dump_block_fcp->fcp.br_lba); |
---|
1172 | 1420 | DEFINE_IPL_ATTR_RW(dump_fcp, device, "0.0.%04llx\n", "0.0.%llx\n", |
---|
1173 | | - dump_block_fcp->ipl_info.fcp.devno); |
---|
| 1421 | + dump_block_fcp->fcp.devno); |
---|
1174 | 1422 | |
---|
1175 | 1423 | static struct attribute *dump_fcp_attrs[] = { |
---|
1176 | 1424 | &sys_dump_fcp_device_attr.attr, |
---|
.. | .. |
---|
1186 | 1434 | .attrs = dump_fcp_attrs, |
---|
1187 | 1435 | }; |
---|
1188 | 1436 | |
---|
| 1437 | +/* NVME dump device attributes */ |
---|
| 1438 | +DEFINE_IPL_ATTR_RW(dump_nvme, fid, "0x%08llx\n", "%llx\n", |
---|
| 1439 | + dump_block_nvme->nvme.fid); |
---|
| 1440 | +DEFINE_IPL_ATTR_RW(dump_nvme, nsid, "0x%08llx\n", "%llx\n", |
---|
| 1441 | + dump_block_nvme->nvme.nsid); |
---|
| 1442 | +DEFINE_IPL_ATTR_RW(dump_nvme, bootprog, "%lld\n", "%llx\n", |
---|
| 1443 | + dump_block_nvme->nvme.bootprog); |
---|
| 1444 | +DEFINE_IPL_ATTR_RW(dump_nvme, br_lba, "%lld\n", "%llx\n", |
---|
| 1445 | + dump_block_nvme->nvme.br_lba); |
---|
| 1446 | + |
---|
| 1447 | +static struct attribute *dump_nvme_attrs[] = { |
---|
| 1448 | + &sys_dump_nvme_fid_attr.attr, |
---|
| 1449 | + &sys_dump_nvme_nsid_attr.attr, |
---|
| 1450 | + &sys_dump_nvme_bootprog_attr.attr, |
---|
| 1451 | + &sys_dump_nvme_br_lba_attr.attr, |
---|
| 1452 | + NULL, |
---|
| 1453 | +}; |
---|
| 1454 | + |
---|
| 1455 | +static struct attribute_group dump_nvme_attr_group = { |
---|
| 1456 | + .name = IPL_NVME_STR, |
---|
| 1457 | + .attrs = dump_nvme_attrs, |
---|
| 1458 | +}; |
---|
| 1459 | + |
---|
1189 | 1460 | /* CCW dump device attributes */ |
---|
1190 | | -DEFINE_IPL_CCW_ATTR_RW(dump_ccw, device, dump_block_ccw->ipl_info.ccw); |
---|
| 1461 | +DEFINE_IPL_CCW_ATTR_RW(dump_ccw, device, dump_block_ccw->ccw); |
---|
1191 | 1462 | |
---|
1192 | 1463 | static struct attribute *dump_ccw_attrs[] = { |
---|
1193 | 1464 | &sys_dump_ccw_device_attr.attr, |
---|
.. | .. |
---|
1227 | 1498 | rc = dump_set_type(DUMP_TYPE_CCW); |
---|
1228 | 1499 | else if (strncmp(buf, DUMP_FCP_STR, strlen(DUMP_FCP_STR)) == 0) |
---|
1229 | 1500 | rc = dump_set_type(DUMP_TYPE_FCP); |
---|
| 1501 | + else if (strncmp(buf, DUMP_NVME_STR, strlen(DUMP_NVME_STR)) == 0) |
---|
| 1502 | + rc = dump_set_type(DUMP_TYPE_NVME); |
---|
1230 | 1503 | return (rc != 0) ? rc : len; |
---|
1231 | 1504 | } |
---|
1232 | 1505 | |
---|
.. | .. |
---|
1254 | 1527 | case DUMP_TYPE_FCP: |
---|
1255 | 1528 | diag308_dump(dump_block_fcp); |
---|
1256 | 1529 | break; |
---|
| 1530 | + case DUMP_TYPE_NVME: |
---|
| 1531 | + diag308_dump(dump_block_nvme); |
---|
| 1532 | + break; |
---|
1257 | 1533 | default: |
---|
1258 | 1534 | break; |
---|
1259 | 1535 | } |
---|
.. | .. |
---|
1279 | 1555 | free_page((unsigned long)dump_block_ccw); |
---|
1280 | 1556 | return rc; |
---|
1281 | 1557 | } |
---|
1282 | | - dump_block_ccw->hdr.len = IPL_PARM_BLK_CCW_LEN; |
---|
| 1558 | + dump_block_ccw->hdr.len = IPL_BP_CCW_LEN; |
---|
1283 | 1559 | dump_block_ccw->hdr.version = IPL_PARM_BLOCK_VERSION; |
---|
1284 | | - dump_block_ccw->hdr.blk0_len = IPL_PARM_BLK0_CCW_LEN; |
---|
1285 | | - dump_block_ccw->hdr.pbt = DIAG308_IPL_TYPE_CCW; |
---|
| 1560 | + dump_block_ccw->ccw.len = IPL_BP0_CCW_LEN; |
---|
| 1561 | + dump_block_ccw->ccw.pbt = IPL_PBT_CCW; |
---|
1286 | 1562 | dump_capabilities |= DUMP_TYPE_CCW; |
---|
1287 | 1563 | return 0; |
---|
1288 | 1564 | } |
---|
.. | .. |
---|
1301 | 1577 | free_page((unsigned long)dump_block_fcp); |
---|
1302 | 1578 | return rc; |
---|
1303 | 1579 | } |
---|
1304 | | - dump_block_fcp->hdr.len = IPL_PARM_BLK_FCP_LEN; |
---|
| 1580 | + dump_block_fcp->hdr.len = IPL_BP_FCP_LEN; |
---|
1305 | 1581 | dump_block_fcp->hdr.version = IPL_PARM_BLOCK_VERSION; |
---|
1306 | | - dump_block_fcp->hdr.blk0_len = IPL_PARM_BLK0_FCP_LEN; |
---|
1307 | | - dump_block_fcp->hdr.pbt = DIAG308_IPL_TYPE_FCP; |
---|
1308 | | - dump_block_fcp->ipl_info.fcp.opt = DIAG308_IPL_OPT_DUMP; |
---|
| 1582 | + dump_block_fcp->fcp.len = IPL_BP0_FCP_LEN; |
---|
| 1583 | + dump_block_fcp->fcp.pbt = IPL_PBT_FCP; |
---|
| 1584 | + dump_block_fcp->fcp.opt = IPL_PB0_FCP_OPT_DUMP; |
---|
1309 | 1585 | dump_capabilities |= DUMP_TYPE_FCP; |
---|
| 1586 | + return 0; |
---|
| 1587 | +} |
---|
| 1588 | + |
---|
| 1589 | +static int __init dump_nvme_init(void) |
---|
| 1590 | +{ |
---|
| 1591 | + int rc; |
---|
| 1592 | + |
---|
| 1593 | + if (!sclp_ipl_info.has_dump) |
---|
| 1594 | + return 0; /* LDIPL DUMP is not installed */ |
---|
| 1595 | + dump_block_nvme = (void *) get_zeroed_page(GFP_KERNEL); |
---|
| 1596 | + if (!dump_block_nvme) |
---|
| 1597 | + return -ENOMEM; |
---|
| 1598 | + rc = sysfs_create_group(&dump_kset->kobj, &dump_nvme_attr_group); |
---|
| 1599 | + if (rc) { |
---|
| 1600 | + free_page((unsigned long)dump_block_nvme); |
---|
| 1601 | + return rc; |
---|
| 1602 | + } |
---|
| 1603 | + dump_block_nvme->hdr.len = IPL_BP_NVME_LEN; |
---|
| 1604 | + dump_block_nvme->hdr.version = IPL_PARM_BLOCK_VERSION; |
---|
| 1605 | + dump_block_nvme->fcp.len = IPL_BP0_NVME_LEN; |
---|
| 1606 | + dump_block_nvme->fcp.pbt = IPL_PBT_NVME; |
---|
| 1607 | + dump_block_nvme->fcp.opt = IPL_PB0_NVME_OPT_DUMP; |
---|
| 1608 | + dump_capabilities |= DUMP_TYPE_NVME; |
---|
1310 | 1609 | return 0; |
---|
1311 | 1610 | } |
---|
1312 | 1611 | |
---|
.. | .. |
---|
1326 | 1625 | if (rc) |
---|
1327 | 1626 | return rc; |
---|
1328 | 1627 | rc = dump_fcp_init(); |
---|
| 1628 | + if (rc) |
---|
| 1629 | + return rc; |
---|
| 1630 | + rc = dump_nvme_init(); |
---|
1329 | 1631 | if (rc) |
---|
1330 | 1632 | return rc; |
---|
1331 | 1633 | dump_set_type(DUMP_TYPE_NONE); |
---|
.. | .. |
---|
1429 | 1731 | { |
---|
1430 | 1732 | if (strcmp(trigger->name, ON_PANIC_STR) == 0 || |
---|
1431 | 1733 | strcmp(trigger->name, ON_RESTART_STR) == 0) |
---|
1432 | | - disabled_wait((unsigned long) __builtin_return_address(0)); |
---|
| 1734 | + disabled_wait(); |
---|
1433 | 1735 | smp_stop_cpu(); |
---|
1434 | 1736 | } |
---|
1435 | 1737 | |
---|
.. | .. |
---|
1664 | 1966 | * READ SCP info provides the correct value. |
---|
1665 | 1967 | */ |
---|
1666 | 1968 | if (memcmp(sclp_ipl_info.loadparm, str, sizeof(str)) == 0 && ipl_block_valid) |
---|
1667 | | - memcpy(sclp_ipl_info.loadparm, ipl_block.hdr.loadparm, LOADPARM_LEN); |
---|
| 1969 | + memcpy(sclp_ipl_info.loadparm, ipl_block.ccw.loadparm, LOADPARM_LEN); |
---|
1668 | 1970 | shutdown_actions_init(); |
---|
1669 | 1971 | shutdown_triggers_init(); |
---|
1670 | 1972 | return 0; |
---|
.. | .. |
---|
1749 | 2051 | ipl_info.type = get_ipl_type(); |
---|
1750 | 2052 | switch (ipl_info.type) { |
---|
1751 | 2053 | case IPL_TYPE_CCW: |
---|
1752 | | - ipl_info.data.ccw.dev_id.ssid = ipl_block.ipl_info.ccw.ssid; |
---|
1753 | | - ipl_info.data.ccw.dev_id.devno = ipl_block.ipl_info.ccw.devno; |
---|
| 2054 | + ipl_info.data.ccw.dev_id.ssid = ipl_block.ccw.ssid; |
---|
| 2055 | + ipl_info.data.ccw.dev_id.devno = ipl_block.ccw.devno; |
---|
1754 | 2056 | break; |
---|
1755 | 2057 | case IPL_TYPE_FCP: |
---|
1756 | 2058 | case IPL_TYPE_FCP_DUMP: |
---|
1757 | 2059 | ipl_info.data.fcp.dev_id.ssid = 0; |
---|
1758 | | - ipl_info.data.fcp.dev_id.devno = ipl_block.ipl_info.fcp.devno; |
---|
1759 | | - ipl_info.data.fcp.wwpn = ipl_block.ipl_info.fcp.wwpn; |
---|
1760 | | - ipl_info.data.fcp.lun = ipl_block.ipl_info.fcp.lun; |
---|
| 2060 | + ipl_info.data.fcp.dev_id.devno = ipl_block.fcp.devno; |
---|
| 2061 | + ipl_info.data.fcp.wwpn = ipl_block.fcp.wwpn; |
---|
| 2062 | + ipl_info.data.fcp.lun = ipl_block.fcp.lun; |
---|
| 2063 | + break; |
---|
| 2064 | + case IPL_TYPE_NVME: |
---|
| 2065 | + case IPL_TYPE_NVME_DUMP: |
---|
| 2066 | + ipl_info.data.nvme.fid = ipl_block.nvme.fid; |
---|
| 2067 | + ipl_info.data.nvme.nsid = ipl_block.nvme.nsid; |
---|
1761 | 2068 | break; |
---|
1762 | 2069 | case IPL_TYPE_NSS: |
---|
1763 | 2070 | case IPL_TYPE_UNKNOWN: |
---|
.. | .. |
---|
1767 | 2074 | atomic_notifier_chain_register(&panic_notifier_list, &on_panic_nb); |
---|
1768 | 2075 | } |
---|
1769 | 2076 | |
---|
1770 | | -void __init ipl_store_parameters(void) |
---|
1771 | | -{ |
---|
1772 | | - int rc; |
---|
1773 | | - |
---|
1774 | | - rc = diag308(DIAG308_STORE, &ipl_block); |
---|
1775 | | - if (rc == DIAG308_RC_OK && ipl_block.hdr.version <= IPL_MAX_SUPPORTED_VERSION) |
---|
1776 | | - ipl_block_valid = 1; |
---|
1777 | | -} |
---|
1778 | | - |
---|
1779 | 2077 | void s390_reset_system(void) |
---|
1780 | 2078 | { |
---|
1781 | 2079 | /* Disable prefixing */ |
---|
.. | .. |
---|
1783 | 2081 | |
---|
1784 | 2082 | /* Disable lowcore protection */ |
---|
1785 | 2083 | __ctl_clear_bit(0, 28); |
---|
1786 | | - diag308_reset(); |
---|
| 2084 | + diag_dma_ops.diag308_reset(); |
---|
1787 | 2085 | } |
---|
| 2086 | + |
---|
| 2087 | +#ifdef CONFIG_KEXEC_FILE |
---|
| 2088 | + |
---|
| 2089 | +int ipl_report_add_component(struct ipl_report *report, struct kexec_buf *kbuf, |
---|
| 2090 | + unsigned char flags, unsigned short cert) |
---|
| 2091 | +{ |
---|
| 2092 | + struct ipl_report_component *comp; |
---|
| 2093 | + |
---|
| 2094 | + comp = vzalloc(sizeof(*comp)); |
---|
| 2095 | + if (!comp) |
---|
| 2096 | + return -ENOMEM; |
---|
| 2097 | + list_add_tail(&comp->list, &report->components); |
---|
| 2098 | + |
---|
| 2099 | + comp->entry.addr = kbuf->mem; |
---|
| 2100 | + comp->entry.len = kbuf->memsz; |
---|
| 2101 | + comp->entry.flags = flags; |
---|
| 2102 | + comp->entry.certificate_index = cert; |
---|
| 2103 | + |
---|
| 2104 | + report->size += sizeof(comp->entry); |
---|
| 2105 | + |
---|
| 2106 | + return 0; |
---|
| 2107 | +} |
---|
| 2108 | + |
---|
| 2109 | +int ipl_report_add_certificate(struct ipl_report *report, void *key, |
---|
| 2110 | + unsigned long addr, unsigned long len) |
---|
| 2111 | +{ |
---|
| 2112 | + struct ipl_report_certificate *cert; |
---|
| 2113 | + |
---|
| 2114 | + cert = vzalloc(sizeof(*cert)); |
---|
| 2115 | + if (!cert) |
---|
| 2116 | + return -ENOMEM; |
---|
| 2117 | + list_add_tail(&cert->list, &report->certificates); |
---|
| 2118 | + |
---|
| 2119 | + cert->entry.addr = addr; |
---|
| 2120 | + cert->entry.len = len; |
---|
| 2121 | + cert->key = key; |
---|
| 2122 | + |
---|
| 2123 | + report->size += sizeof(cert->entry); |
---|
| 2124 | + report->size += cert->entry.len; |
---|
| 2125 | + |
---|
| 2126 | + return 0; |
---|
| 2127 | +} |
---|
| 2128 | + |
---|
| 2129 | +struct ipl_report *ipl_report_init(struct ipl_parameter_block *ipib) |
---|
| 2130 | +{ |
---|
| 2131 | + struct ipl_report *report; |
---|
| 2132 | + |
---|
| 2133 | + report = vzalloc(sizeof(*report)); |
---|
| 2134 | + if (!report) |
---|
| 2135 | + return ERR_PTR(-ENOMEM); |
---|
| 2136 | + |
---|
| 2137 | + report->ipib = ipib; |
---|
| 2138 | + INIT_LIST_HEAD(&report->components); |
---|
| 2139 | + INIT_LIST_HEAD(&report->certificates); |
---|
| 2140 | + |
---|
| 2141 | + report->size = ALIGN(ipib->hdr.len, 8); |
---|
| 2142 | + report->size += sizeof(struct ipl_rl_hdr); |
---|
| 2143 | + report->size += sizeof(struct ipl_rb_components); |
---|
| 2144 | + report->size += sizeof(struct ipl_rb_certificates); |
---|
| 2145 | + |
---|
| 2146 | + return report; |
---|
| 2147 | +} |
---|
| 2148 | + |
---|
| 2149 | +void *ipl_report_finish(struct ipl_report *report) |
---|
| 2150 | +{ |
---|
| 2151 | + struct ipl_report_certificate *cert; |
---|
| 2152 | + struct ipl_report_component *comp; |
---|
| 2153 | + struct ipl_rb_certificates *certs; |
---|
| 2154 | + struct ipl_parameter_block *ipib; |
---|
| 2155 | + struct ipl_rb_components *comps; |
---|
| 2156 | + struct ipl_rl_hdr *rl_hdr; |
---|
| 2157 | + void *buf, *ptr; |
---|
| 2158 | + |
---|
| 2159 | + buf = vzalloc(report->size); |
---|
| 2160 | + if (!buf) |
---|
| 2161 | + goto out; |
---|
| 2162 | + ptr = buf; |
---|
| 2163 | + |
---|
| 2164 | + memcpy(ptr, report->ipib, report->ipib->hdr.len); |
---|
| 2165 | + ipib = ptr; |
---|
| 2166 | + if (ipl_secure_flag) |
---|
| 2167 | + ipib->hdr.flags |= IPL_PL_FLAG_SIPL; |
---|
| 2168 | + ipib->hdr.flags |= IPL_PL_FLAG_IPLSR; |
---|
| 2169 | + ptr += report->ipib->hdr.len; |
---|
| 2170 | + ptr = PTR_ALIGN(ptr, 8); |
---|
| 2171 | + |
---|
| 2172 | + rl_hdr = ptr; |
---|
| 2173 | + ptr += sizeof(*rl_hdr); |
---|
| 2174 | + |
---|
| 2175 | + comps = ptr; |
---|
| 2176 | + comps->rbt = IPL_RBT_COMPONENTS; |
---|
| 2177 | + ptr += sizeof(*comps); |
---|
| 2178 | + list_for_each_entry(comp, &report->components, list) { |
---|
| 2179 | + memcpy(ptr, &comp->entry, sizeof(comp->entry)); |
---|
| 2180 | + ptr += sizeof(comp->entry); |
---|
| 2181 | + } |
---|
| 2182 | + comps->len = ptr - (void *)comps; |
---|
| 2183 | + |
---|
| 2184 | + certs = ptr; |
---|
| 2185 | + certs->rbt = IPL_RBT_CERTIFICATES; |
---|
| 2186 | + ptr += sizeof(*certs); |
---|
| 2187 | + list_for_each_entry(cert, &report->certificates, list) { |
---|
| 2188 | + memcpy(ptr, &cert->entry, sizeof(cert->entry)); |
---|
| 2189 | + ptr += sizeof(cert->entry); |
---|
| 2190 | + } |
---|
| 2191 | + certs->len = ptr - (void *)certs; |
---|
| 2192 | + rl_hdr->len = ptr - (void *)rl_hdr; |
---|
| 2193 | + |
---|
| 2194 | + list_for_each_entry(cert, &report->certificates, list) { |
---|
| 2195 | + memcpy(ptr, cert->key, cert->entry.len); |
---|
| 2196 | + ptr += cert->entry.len; |
---|
| 2197 | + } |
---|
| 2198 | + |
---|
| 2199 | + BUG_ON(ptr > buf + report->size); |
---|
| 2200 | +out: |
---|
| 2201 | + return buf; |
---|
| 2202 | +} |
---|
| 2203 | + |
---|
| 2204 | +int ipl_report_free(struct ipl_report *report) |
---|
| 2205 | +{ |
---|
| 2206 | + struct ipl_report_component *comp, *ncomp; |
---|
| 2207 | + struct ipl_report_certificate *cert, *ncert; |
---|
| 2208 | + |
---|
| 2209 | + list_for_each_entry_safe(comp, ncomp, &report->components, list) |
---|
| 2210 | + vfree(comp); |
---|
| 2211 | + |
---|
| 2212 | + list_for_each_entry_safe(cert, ncert, &report->certificates, list) |
---|
| 2213 | + vfree(cert); |
---|
| 2214 | + |
---|
| 2215 | + vfree(report); |
---|
| 2216 | + |
---|
| 2217 | + return 0; |
---|
| 2218 | +} |
---|
| 2219 | + |
---|
| 2220 | +#endif |
---|