From 30232e2023a724bc562e38ba0daf78c0947e673f24520c5ee7b4094edf12baab Mon Sep 17 00:00:00 2001 From: Mark Post Date: Thu, 19 Mar 2020 22:52:46 +0000 Subject: [PATCH] Accepting request 786614 from home:markkp:branches:Base:System - Added the following patches for bsc#1166850 zipl: fix secure boot config handling: * s390-tools-sles15sp2-01-zipl-Add-missing-options-to-help-output.patch * s390-tools-sles15sp2-02-zipl-allow-stand-alone-secure-option-on-command-l.patch * s390-tools-sles15sp2-03-zipl-correct-secure-boot-config-handling.patch * s390-tools-sles15sp2-04-zipl-fix-zipl.conf-man-page-example-for-secure-boot.patch - Modified the spec file so that the kernel used for the SCSI dump tool is named zfcpdump-image instead of zfcpdump_part.image. This is to match the new version of zipl that expects this new file name. (bsc#1166851) - Added the following patches to implement jsc#SLE-7471, Enhanced tooling for kvm guest images (bsc#1165549): * s390-tools-sles15sp2-01-zipl-fix-Wdiscarded-qualifiers.patch * s390-tools-sles15sp2-02-zipl-fix-Waddress-of-packed-member.patch * s390-tools-sles15sp2-03-zipl-remove-some-useless-__packed___-attributes.patch * s390-tools-sles15sp2-04-zipl-Fix-entry-point-for-stand-alone-kdump.patch * s390-tools-sles15sp2-05-zipl-Fix-dependency-generation-in-zipl-boot.patch * s390-tools-sles15sp2-06-zipl-Make-use-of-__packed-macro.patch * s390-tools-sles15sp2-07-zipl-define-__section-macro-and-make-use-of-it.patch * s390-tools-sles15sp2-08-zipl-Make-use-of-__noreturn-macro.patch * s390-tools-sles15sp2-09-zipl-Define-__noinline-macro-and-make-use-of-it.patch * s390-tools-sles15sp2-10-zipl-stage3-Mark-start_kernel-__noreturn.patch * s390-tools-sles15sp2-11-zipl-sclp-Remove-duplicate-macros.patch * s390-tools-sles15sp2-12-zipl-Make-address-size-mask-macros-UL.patch * s390-tools-sles15sp2-13-zipl-libc-Use-stdint.h-instead-of-self-defined-macro.patch * s390-tools-sles15sp2-14-zipl-Consolidate-IMAGE-macros.patch * s390-tools-sles15sp2-15-zipl-Consolidate-STAGE-2-3-macros.patch * s390-tools-sles15sp2-16-zipl-stfle-use-uint64_t-instead-of-u64.patch * s390-tools-sles15sp2-17-zipl-boot-fix-comment-in-stage3.lds.patch * s390-tools-sles15sp2-18-lib-zt_common-add-STATIC_ASSERT-macro.patch * s390-tools-sles15sp2-19-zipl-use-STATIC_ASSERT-macro-for-no-padding-verifica.patch * s390-tools-sles15sp2-20-Support-lib-zt_common.h-to-be-used-in-assembler-and-.patch * s390-tools-sles15sp2-21-zipl-move-IPL-related-definitions-into-separate-head.patch * s390-tools-sles15sp2-22-zipl-move-SIGP-related-functions-and-definitions-int.patch * s390-tools-sles15sp2-23-zipl-add-SIGP_SET_ARCHITECTURE-to-sigp.h-and-use-it.patch * s390-tools-sles15sp2-24-zipl-stage3-make-IPL_DEVICE-definition-consistent-wi.patch * s390-tools-sles15sp2-25-zipl-move-Linux-layout-definitions-into-separate-hea.patch * s390-tools-sles15sp2-26-zipl-tape0-use-constants-defined-in-linux_layout.h.patch * s390-tools-sles15sp2-27-zipl-use-STAGE3_ENTRY-for-STAGE3_LOAD_ADDRESS.patch * s390-tools-sles15sp2-28-zipl-move-loaders-layout-definitions-into-separate-h.patch * s390-tools-sles15sp2-29-zipl-s390.h-rename-inline-macro-into-__always_inline.patch * s390-tools-sles15sp2-30-zipl-move-__always_inline-barrier-__pa32-pa-to-zt_co.patch * s390-tools-sles15sp2-31-zipl-make-BLK_PWRT-unsigned-int.patch * s390-tools-sles15sp2-32-Consolidate-MIN-and-MAX-macros.patch * s390-tools-sles15sp2-33-zipl-remove-libc.h-include-in-s390.h.patch * s390-tools-sles15sp2-34-zipl-move-s390.h-to-include-boot-s390.h.patch * s390-tools-sles15sp2-35-zipl-libc-include-s390.h.patch * s390-tools-sles15sp2-36-include-boot-s390.h-move-panic-and-panic_notify-to-l.patch * s390-tools-sles15sp2-37-include-boot-s390.h-fixes-for-Werror-sign-conversion.patch * s390-tools-sles15sp2-38-zipl-refactor-all-EBCDIC-code-into-separate-files.patch * s390-tools-sles15sp2-39-zipl-sclp-add-macros-for-the-control-program-masks.patch * s390-tools-sles15sp2-40-zipl-sclp-add-sclp_print_ascii.patch * s390-tools-sles15sp2-41-zipl-libc-printf-print-on-linemode-and-ASCII-console.patch * s390-tools-sles15sp2-42-Consolidate-ALIGN-__ALIGN_MASK-ARRAY_SIZE-macros.patch * s390-tools-sles15sp2-43-genprotimg-boot-initial-bootloader-support.patch * s390-tools-sles15sp2-44-genprotimg-boot-use-C-pre-processor-for-linker-scrip.patch * s390-tools-sles15sp2-45-genprotimg-add-relocator-for-stage3b.patch * s390-tools-sles15sp2-46-README.md-remove-useless-empty-line.patch * s390-tools-sles15sp2-47-include-boot-s390.h-add-guard-for-struct-__vector128.patch * s390-tools-sles15sp2-48-genprotimg-introduce-new-tool-for-the-creation-of-PV.patch - Added a BuildRequires for glib2-devel to support the new feature. - Added a %dir entry for /usr/share/s390-tools/genprotimg OBS-URL: https://build.opensuse.org/request/show/786614 OBS-URL: https://build.opensuse.org/package/show/Base:System/s390-tools?expand=0&rev=92 --- s390-tools-rpmlintrc | 1 + ...l-Add-missing-options-to-help-output.patch | 63 + ...p2-01-zipl-fix-Wdiscarded-qualifiers.patch | 45 + ...and-alone-secure-option-on-command-l.patch | 170 + ...2-zipl-fix-Waddress-of-packed-member.patch | 102 + ...-correct-secure-boot-config-handling.patch | 187 + ...-some-useless-__packed___-attributes.patch | 143 + ...ix-entry-point-for-stand-alone-kdump.patch | 95 + ...onf-man-page-example-for-secure-boot.patch | 70 + ...x-dependency-generation-in-zipl-boot.patch | 76 + ...2-06-zipl-Make-use-of-__packed-macro.patch | 349 ++ ...e-__section-macro-and-make-use-of-it.patch | 188 + ...08-zipl-Make-use-of-__noreturn-macro.patch | 61 + ...-__noinline-macro-and-make-use-of-it.patch | 66 + ...-stage3-Mark-start_kernel-__noreturn.patch | 49 + ...11-zipl-sclp-Remove-duplicate-macros.patch | 41 + ...ipl-Make-address-size-mask-macros-UL.patch | 116 + ...dint.h-instead-of-self-defined-macro.patch | 52 + ...sp2-14-zipl-Consolidate-IMAGE-macros.patch | 199 + ...15-zipl-Consolidate-STAGE-2-3-macros.patch | 110 + ...pl-stfle-use-uint64_t-instead-of-u64.patch | 53 + ...-zipl-boot-fix-comment-in-stage3.lds.patch | 42 + ...ib-zt_common-add-STATIC_ASSERT-macro.patch | 50 + ...ASSERT-macro-for-no-padding-verifica.patch | 91 + ...ommon.h-to-be-used-in-assembler-and-.patch | 65 + ...lated-definitions-into-separate-head.patch | 359 ++ ...elated-functions-and-definitions-int.patch | 148 + ...ET_ARCHITECTURE-to-sigp.h-and-use-it.patch | 117 + ...-IPL_DEVICE-definition-consistent-wi.patch | 56 + ...layout-definitions-into-separate-hea.patch | 109 + ...-constants-defined-in-linux_layout.h.patch | 79 + ...STAGE3_ENTRY-for-STAGE3_LOAD_ADDRESS.patch | 45 + ...s-layout-definitions-into-separate-h.patch | 105 + ...me-inline-macro-into-__always_inline.patch | 192 + ...ys_inline-barrier-__pa32-pa-to-zt_co.patch | 74 + ...2-31-zipl-make-BLK_PWRT-unsigned-int.patch | 44 + ...p2-32-Consolidate-MIN-and-MAX-macros.patch | 105 + ...zipl-remove-libc.h-include-in-s390.h.patch | 76 + ...l-move-s390.h-to-include-boot-s390.h.patch | 1129 ++++ ...les15sp2-35-zipl-libc-include-s390.h.patch | 51 + ...0.h-move-panic-and-panic_notify-to-l.patch | 69 + ...0.h-fixes-for-Werror-sign-conversion.patch | 73 + ...-all-EBCDIC-code-into-separate-files.patch | 640 ++ ...macros-for-the-control-program-masks.patch | 79 + ...p2-40-zipl-sclp-add-sclp_print_ascii.patch | 163 + ...-print-on-linemode-and-ASCII-console.patch | 47 + ...ALIGN-__ALIGN_MASK-ARRAY_SIZE-macros.patch | 134 + ...timg-boot-initial-bootloader-support.patch | 803 +++ ...use-C-pre-processor-for-linker-scrip.patch | 479 ++ ...genprotimg-add-relocator-for-stage3b.patch | 120 + ...-README.md-remove-useless-empty-line.patch | 38 + ...0.h-add-guard-for-struct-__vector128.patch | 54 + ...duce-new-tool-for-the-creation-of-PV.patch | 5198 +++++++++++++++++ s390-tools.changes | 70 + s390-tools.spec | 58 +- 55 files changed, 13196 insertions(+), 2 deletions(-) create mode 100644 s390-tools-sles15sp2-01-zipl-Add-missing-options-to-help-output.patch create mode 100644 s390-tools-sles15sp2-01-zipl-fix-Wdiscarded-qualifiers.patch create mode 100644 s390-tools-sles15sp2-02-zipl-allow-stand-alone-secure-option-on-command-l.patch create mode 100644 s390-tools-sles15sp2-02-zipl-fix-Waddress-of-packed-member.patch create mode 100644 s390-tools-sles15sp2-03-zipl-correct-secure-boot-config-handling.patch create mode 100644 s390-tools-sles15sp2-03-zipl-remove-some-useless-__packed___-attributes.patch create mode 100644 s390-tools-sles15sp2-04-zipl-Fix-entry-point-for-stand-alone-kdump.patch create mode 100644 s390-tools-sles15sp2-04-zipl-fix-zipl.conf-man-page-example-for-secure-boot.patch create mode 100644 s390-tools-sles15sp2-05-zipl-Fix-dependency-generation-in-zipl-boot.patch create mode 100644 s390-tools-sles15sp2-06-zipl-Make-use-of-__packed-macro.patch create mode 100644 s390-tools-sles15sp2-07-zipl-define-__section-macro-and-make-use-of-it.patch create mode 100644 s390-tools-sles15sp2-08-zipl-Make-use-of-__noreturn-macro.patch create mode 100644 s390-tools-sles15sp2-09-zipl-Define-__noinline-macro-and-make-use-of-it.patch create mode 100644 s390-tools-sles15sp2-10-zipl-stage3-Mark-start_kernel-__noreturn.patch create mode 100644 s390-tools-sles15sp2-11-zipl-sclp-Remove-duplicate-macros.patch create mode 100644 s390-tools-sles15sp2-12-zipl-Make-address-size-mask-macros-UL.patch create mode 100644 s390-tools-sles15sp2-13-zipl-libc-Use-stdint.h-instead-of-self-defined-macro.patch create mode 100644 s390-tools-sles15sp2-14-zipl-Consolidate-IMAGE-macros.patch create mode 100644 s390-tools-sles15sp2-15-zipl-Consolidate-STAGE-2-3-macros.patch create mode 100644 s390-tools-sles15sp2-16-zipl-stfle-use-uint64_t-instead-of-u64.patch create mode 100644 s390-tools-sles15sp2-17-zipl-boot-fix-comment-in-stage3.lds.patch create mode 100644 s390-tools-sles15sp2-18-lib-zt_common-add-STATIC_ASSERT-macro.patch create mode 100644 s390-tools-sles15sp2-19-zipl-use-STATIC_ASSERT-macro-for-no-padding-verifica.patch create mode 100644 s390-tools-sles15sp2-20-Support-lib-zt_common.h-to-be-used-in-assembler-and-.patch create mode 100644 s390-tools-sles15sp2-21-zipl-move-IPL-related-definitions-into-separate-head.patch create mode 100644 s390-tools-sles15sp2-22-zipl-move-SIGP-related-functions-and-definitions-int.patch create mode 100644 s390-tools-sles15sp2-23-zipl-add-SIGP_SET_ARCHITECTURE-to-sigp.h-and-use-it.patch create mode 100644 s390-tools-sles15sp2-24-zipl-stage3-make-IPL_DEVICE-definition-consistent-wi.patch create mode 100644 s390-tools-sles15sp2-25-zipl-move-Linux-layout-definitions-into-separate-hea.patch create mode 100644 s390-tools-sles15sp2-26-zipl-tape0-use-constants-defined-in-linux_layout.h.patch create mode 100644 s390-tools-sles15sp2-27-zipl-use-STAGE3_ENTRY-for-STAGE3_LOAD_ADDRESS.patch create mode 100644 s390-tools-sles15sp2-28-zipl-move-loaders-layout-definitions-into-separate-h.patch create mode 100644 s390-tools-sles15sp2-29-zipl-s390.h-rename-inline-macro-into-__always_inline.patch create mode 100644 s390-tools-sles15sp2-30-zipl-move-__always_inline-barrier-__pa32-pa-to-zt_co.patch create mode 100644 s390-tools-sles15sp2-31-zipl-make-BLK_PWRT-unsigned-int.patch create mode 100644 s390-tools-sles15sp2-32-Consolidate-MIN-and-MAX-macros.patch create mode 100644 s390-tools-sles15sp2-33-zipl-remove-libc.h-include-in-s390.h.patch create mode 100644 s390-tools-sles15sp2-34-zipl-move-s390.h-to-include-boot-s390.h.patch create mode 100644 s390-tools-sles15sp2-35-zipl-libc-include-s390.h.patch create mode 100644 s390-tools-sles15sp2-36-include-boot-s390.h-move-panic-and-panic_notify-to-l.patch create mode 100644 s390-tools-sles15sp2-37-include-boot-s390.h-fixes-for-Werror-sign-conversion.patch create mode 100644 s390-tools-sles15sp2-38-zipl-refactor-all-EBCDIC-code-into-separate-files.patch create mode 100644 s390-tools-sles15sp2-39-zipl-sclp-add-macros-for-the-control-program-masks.patch create mode 100644 s390-tools-sles15sp2-40-zipl-sclp-add-sclp_print_ascii.patch create mode 100644 s390-tools-sles15sp2-41-zipl-libc-printf-print-on-linemode-and-ASCII-console.patch create mode 100644 s390-tools-sles15sp2-42-Consolidate-ALIGN-__ALIGN_MASK-ARRAY_SIZE-macros.patch create mode 100644 s390-tools-sles15sp2-43-genprotimg-boot-initial-bootloader-support.patch create mode 100644 s390-tools-sles15sp2-44-genprotimg-boot-use-C-pre-processor-for-linker-scrip.patch create mode 100644 s390-tools-sles15sp2-45-genprotimg-add-relocator-for-stage3b.patch create mode 100644 s390-tools-sles15sp2-46-README.md-remove-useless-empty-line.patch create mode 100644 s390-tools-sles15sp2-47-include-boot-s390.h-add-guard-for-struct-__vector128.patch create mode 100644 s390-tools-sles15sp2-48-genprotimg-introduce-new-tool-for-the-creation-of-PV.patch diff --git a/s390-tools-rpmlintrc b/s390-tools-rpmlintrc index d7d8c9a..89bc72c 100644 --- a/s390-tools-rpmlintrc +++ b/s390-tools-rpmlintrc @@ -1,3 +1,4 @@ +addFilter("/var/log/ts-shell") addFilter("statically-linked-binary /usr/lib/s390-tools/.*") addFilter("statically-linked-binary /usr/bin/read_values") addFilter("systemd-service-without-service_.* *@.service") diff --git a/s390-tools-sles15sp2-01-zipl-Add-missing-options-to-help-output.patch b/s390-tools-sles15sp2-01-zipl-Add-missing-options-to-help-output.patch new file mode 100644 index 0000000..08c4f42 --- /dev/null +++ b/s390-tools-sles15sp2-01-zipl-Add-missing-options-to-help-output.patch @@ -0,0 +1,63 @@ +Subject: [PATCH] [BZ 184396] zipl: Add missing options to help output +From: Stefan Haberland + +Description: zipl: fix secure boot config handling +Symptom: The config file parsing for secure boot worked not as + it was expected to be. For example a config section + setting was not evaluated properly. + It is not possible to specify command line option -S + without other options. + Additionally the man page showed an invalid example. +Problem: The config file parsing was not implemented properly. +Solution: The hierarchy of the secure boot settings in the config + file is: + defaultboot > menu > section + Allow that --secure or -S is specified on command line + without the need to allow all options on the command + line. Also ensure that the command line option + overrules the config option and correctly ensure that + secure boot is only set for SCSI devices. + Fix man page example. +Reproduction: Run zipl with a secure= setting in a configuration + section or specify -S on command line. +Upstream-ID: dcce14923c3e9615df53773d1d8a3a22cbb23b96 +Problem-ID: 184396 + +Upstream-Description: + + zipl: Add missing options to help output + + Reviewed-by: Stefan Haberland + Signed-off-by: Jan Hoeppner + + +Signed-off-by: Stefan Haberland +--- + zipl/src/zipl.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +--- a/zipl/src/zipl.c ++++ b/zipl/src/zipl.c +@@ -68,6 +68,8 @@ static const char* usage_text[] = { + "-P, --parameters PARMLINE Use specified kernel PARMLINE", + "-T, --tape TAPEDEV Install bootloader on tape device TAPEDEV", + "-s, --segment SEGMENT,ADDR Install a segment from file SEGMENT", ++"-k, --kdump=auto Install a kdump kernel that can be used as a", ++" stand-alone dump tool", + "-d, --dumpto DUMPDEV[,SIZE] Install a system dump record on tape device", + " or disk partition DUMPDEV", + "-M, --mvdump DEVLIST[,SIZE] Install a multi-volume dump record on each", +@@ -78,7 +80,12 @@ static const char* usage_text[] = { + "-n, --noninteractive Answer all confirmation questions with 'yes'", + "-V, --verbose Provide more verbose output", + "-a, --add-files Add all referenced files to bootmap file", +-" --dry-run Simulate run but don't modify IPL records" ++" --dry-run Simulate run but don't modify IPL records", ++"-S, --secure SWITCH Control the zIPL secure boot support.", ++" auto (default):", ++" Write signatures if available and supported", ++" 1: Write signatures regardless of support", ++" 0: Do not write signatures" + }; + + diff --git a/s390-tools-sles15sp2-01-zipl-fix-Wdiscarded-qualifiers.patch b/s390-tools-sles15sp2-01-zipl-fix-Wdiscarded-qualifiers.patch new file mode 100644 index 0000000..8282701 --- /dev/null +++ b/s390-tools-sles15sp2-01-zipl-fix-Wdiscarded-qualifiers.patch @@ -0,0 +1,45 @@ +Subject: [PATCH] [FEAT VS1804] zipl: fix -Wdiscarded-qualifiers +From: Marc Hartmayer + +Summary: genprotimg: Introduce new tool for the creation of PV images +Description: genprotimg takes a kernel, host-key documents, optionally an + initrd, optionally a file with the kernel command line, and it + generates a single, loadable image file. The image consists of a + concatenation of a plain text boot loader, the encrypted + components for kernel, initrd, and cmdline, and the + integrity-protected PV header, containing metadata necessary for + running the guest in PV mode. It's possible to use this image file + as a kernel for zIPL or for a direct kernel boot using QEMU. +Upstream-ID: bbc46edaf53c2c148b5c94a2414f6847f67f856a +Problem-ID: VS1804 + +Upstream-Description: + + zipl: fix -Wdiscarded-qualifiers + + Reported by GCC 9.2.1 when building with '-Wdiscarded-qualifiers'. + + job.c: In function 'get_job_from_config_file': + job.c:1810:14: warning: assignment discards 'const' qualifier from pointer target type [-Wdiscarded-qualifiers] + + Signed-off-by: Marc Hartmayer + Reviewed-by: Stefan Haberland + Signed-off-by: Jan Höppner + + +Signed-off-by: Marc Hartmayer +--- + zipl/src/job.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/zipl/src/job.c ++++ b/zipl/src/job.c +@@ -1796,7 +1796,7 @@ get_job_from_config_file(struct command_ + { + struct scan_token* scan; + struct scan_token* new_scan; +- char* filename; ++ const char *filename; + char *blsdir; + char* source; + int rc, scan_size; diff --git a/s390-tools-sles15sp2-02-zipl-allow-stand-alone-secure-option-on-command-l.patch b/s390-tools-sles15sp2-02-zipl-allow-stand-alone-secure-option-on-command-l.patch new file mode 100644 index 0000000..d93b981 --- /dev/null +++ b/s390-tools-sles15sp2-02-zipl-allow-stand-alone-secure-option-on-command-l.patch @@ -0,0 +1,170 @@ +Subject: [PATCH] [BZ 184396] zipl: allow stand alone secure option on command line +From: Stefan Haberland + +Description: zipl: fix secure boot config handling +Symptom: The config file parsing for secure boot worked not as + it was expected to be. For example a config section + setting was not evaluated properly. + It is not possible to specify command line option -S + without other options. + Additionally the man page showed an invalid example. +Problem: The config file parsing was not implemented properly. +Solution: The hierarchy of the secure boot settings in the config + file is: + defaultboot > menu > section + Allow that --secure or -S is specified on command line + without the need to allow all options on the command + line. Also ensure that the command line option + overrules the config option and correctly ensure that + secure boot is only set for SCSI devices. + Fix man page example. +Reproduction: Run zipl with a secure= setting in a configuration + section or specify -S on command line. +Upstream-ID: 27f6c0a167da8d08f7f3343360528528f85d661f +Problem-ID: 184396 + +Upstream-Description: + + zipl: allow stand alone secure option on command line + + Allow that --secure or -S is specified on command line without the need to + allow all options on the command line. + Also ensure that the command line option overrules the config option and + correctly ensure that secure boot is only set for SCSI devices. + + Signed-off-by: Stefan Haberland + Reviewed-by: Philipp Rudo + Signed-off-by: Jan Hoeppner + + +Signed-off-by: Stefan Haberland +--- + zipl/src/bootmap.c | 6 ++++++ + zipl/src/job.c | 52 +++++++++++++++++++++++++--------------------------- + 2 files changed, 31 insertions(+), 27 deletions(-) + +--- a/zipl/src/bootmap.c ++++ b/zipl/src/bootmap.c +@@ -1133,6 +1133,12 @@ bootmap_create(struct job_data *job, dis + disk_get_type_name(info->type)); + goto out_disk_free_info; + } ++ /* Check if secure boot was enabled only for SCSI */ ++ if (job->is_secure == SECURE_BOOT_ENABLED && ++ info->type != disk_type_scsi) { ++ error_reason("Secure boot forced for non-SCSI disk type"); ++ goto out_disk_free_info; ++ } + if (verbose) { + printf("Target device information\n"); + disk_print_info(info); +--- a/zipl/src/job.c ++++ b/zipl/src/job.c +@@ -72,6 +72,7 @@ struct command_line { + int add_files; + int dry_run; + int force; ++ int is_secure; + enum scan_section_type type; + }; + +@@ -89,6 +90,22 @@ store_option(struct command_line* cmdlin + return 0; + } + ++static int ++set_secure_ipl(char *keyword, int *is_secure) ++{ ++ if (strcmp(keyword, "auto") == 0) { ++ *is_secure = SECURE_BOOT_AUTO; ++ } else if (strcmp(keyword, "0") == 0) { ++ *is_secure = SECURE_BOOT_DISABLED; ++ } else if (strcmp(keyword, "1") == 0) { ++ *is_secure = SECURE_BOOT_ENABLED; ++ } else { ++ error_reason("Invalid secure boot setting '%s'", ++ keyword); ++ return -1; ++ } ++ return 0; ++} + + static int + get_command_line(int argc, char* argv[], struct command_line* line) +@@ -217,9 +234,7 @@ get_command_line(int argc, char* argv[], + cmdline.menu = optarg; + break; + case 'S': +- is_keyword = 1; +- rc = store_option(&cmdline, scan_keyword_secure, +- optarg); ++ rc = set_secure_ipl(optarg, &cmdline.is_secure); + break; + case 'h': + cmdline.help = 1; +@@ -1270,27 +1285,6 @@ type_from_target(char *target, disk_type + } + + static int +-set_secure_ipl(char *keyword, struct job_data *job) +-{ +- if (strcmp(keyword, "auto") == 0) { +- job->is_secure = SECURE_BOOT_AUTO; +- } else if (strcmp(keyword, "0") == 0) { +- job->is_secure = SECURE_BOOT_DISABLED; +- } else if (strcmp(keyword, "1") == 0) { +- if (job->target.targettype != disk_type_scsi) { +- error_reason("Secure boot forced for non-SCSI disk type"); +- return -1; +- } +- job->is_secure = SECURE_BOOT_ENABLED; +- } else { +- error_reason("Invalid secure boot setting '%s'", +- keyword); +- return -1; +- } +- return 0; +-} +- +-static int + get_job_from_section_data(char* data[], struct job_data* job, char* section) + { + int rc; +@@ -1374,7 +1368,7 @@ get_job_from_section_data(char* data[], + /* Fill in secure boot */ + if (data[(int) scan_keyword_secure] != NULL) { + rc = set_secure_ipl(data[(int) scan_keyword_secure], +- job); ++ &job->is_secure); + if (rc) + return rc; + } +@@ -1538,7 +1532,7 @@ get_menu_job(struct scan_token* scan, ch + case scan_keyword_secure: + rc = set_secure_ipl( + scan[i].content.keyword.value, +- job); ++ &job->is_secure); + if (rc) + return rc; + break; +@@ -1880,7 +1874,6 @@ job_get(int argc, char* argv[], struct j + job->add_files = cmdline.add_files; + job->data.mvdump.force = cmdline.force; + job->dry_run = cmdline.dry_run; +- job->is_secure = SECURE_BOOT_AUTO; + /* Get job data from user input */ + if (cmdline.help) { + job->command_line = 1; +@@ -1899,6 +1892,11 @@ job_get(int argc, char* argv[], struct j + job_free(job); + return rc; + } ++ if (cmdline.is_secure) ++ job->is_secure = cmdline.is_secure; ++ else ++ job->is_secure = job->is_secure ? : SECURE_BOOT_AUTO; ++ + /* Check job data for validity */ + rc = check_job_data(job); + if (rc) { diff --git a/s390-tools-sles15sp2-02-zipl-fix-Waddress-of-packed-member.patch b/s390-tools-sles15sp2-02-zipl-fix-Waddress-of-packed-member.patch new file mode 100644 index 0000000..8416766 --- /dev/null +++ b/s390-tools-sles15sp2-02-zipl-fix-Waddress-of-packed-member.patch @@ -0,0 +1,102 @@ +Subject: [PATCH] [FEAT VS1804] zipl: fix -Waddress-of-packed-member +From: Marc Hartmayer + +Summary: genprotimg: Introduce new tool for the creation of PV images +Description: genprotimg takes a kernel, host-key documents, optionally an + initrd, optionally a file with the kernel command line, and it + generates a single, loadable image file. The image consists of a + concatenation of a plain text boot loader, the encrypted + components for kernel, initrd, and cmdline, and the + integrity-protected PV header, containing metadata necessary for + running the guest in PV mode. It's possible to use this image file + as a kernel for zIPL or for a direct kernel boot using QEMU. +Upstream-ID: aa09b292483eb2d79247260fccc2b456dee01e8d +Problem-ID: VS1804 + +Upstream-Description: + + zipl: fix -Waddress-of-packed-member + + Reported by GCC 9.2.1 when building with '-Waddress-of-packed-member'. + + menu.c: In function 'menu_read': + menu.c:30:22: warning: taking address of packed member of 'struct boot_stage2_params' may result in an unaligned pointer value [-Waddress-of-packed-member] + 30 | uint16_t *configs = __stage2_params.config; + | ^~~~~~~~~~~~~~~ + menu.c: In function 'menu_list': + menu.c:83:22: warning: taking address of packed member of 'struct boot_stage2_params' may result in an unaligned pointer value [-Waddress-of-packed-member] + 83 | uint16_t *configs = __stage2_params.config; + | ^~~~~~~~~~~~~~~ + menu.c: In function 'menu': + menu.c:139:22: warning: taking address of packed member of 'struct boot_stage2_params' may result in an unaligned pointer value [-Waddress-of-packed-member] + 139 | uint16_t *configs = __stage2_params.config; + | ^~~~~~~~~~~~~~~ + + Signed-off-by: Marc Hartmayer + Reviewed-by: Stefan Haberland + Signed-off-by: Jan Höppner + + +Signed-off-by: Marc Hartmayer +--- + zipl/boot/menu.c | 13 +++++-------- + 1 file changed, 5 insertions(+), 8 deletions(-) + +--- a/zipl/boot/menu.c ++++ b/zipl/boot/menu.c +@@ -27,7 +27,6 @@ static void menu_prompt(int timeout) + static int menu_read(void) + { + char *temp_area = (char *)get_zeroed_page(); +- uint16_t *configs = __stage2_params.config; + int timeout, rc, i, count = 0; + char *endptr; + int value; +@@ -60,7 +59,7 @@ static int menu_read(void) + value = ebcstrtoul((char *)temp_area, &endptr, 10); + + if ((endptr != temp_area) && (value < BOOT_MENU_ENTRIES - 1) && +- (configs[value] != 0)) { ++ (__stage2_params.config[value] != 0)) { + /* valid config found - finish */ + break; + } else { +@@ -80,14 +79,13 @@ out_free_page: + + static int menu_list(void) + { +- uint16_t *configs = __stage2_params.config; + char *name; + int i; + + for (i = 0; i < BOOT_MENU_ENTRIES; i++) { +- if (configs[i] == 0) ++ if (__stage2_params.config[i] == 0) + continue; +- name = configs[i] + ((void *)&__stage2_params); ++ name = __stage2_params.config[i] + ((void *)&__stage2_params); + printf("%s\n", name); + if (i == 0) + printf("\n"); +@@ -136,7 +134,6 @@ static int menu_param(unsigned long *val + + int menu(void) + { +- uint16_t *configs = __stage2_params.config; + unsigned long value = 0; + char *cmd_line_extra; + char endstring[15]; +@@ -181,11 +178,11 @@ int menu(void) + + boot: + /* sanity - config entry not valid */ +- if (configs[value] == 0) ++ if (__stage2_params.config[value] == 0) + panic(EINTERNAL, "%s", msg_econfig); + + printf("Booting %s\n", +- (char *)(configs[value] + ++ (char *)(__stage2_params.config[value] + + (void *)&__stage2_params + TEXT_OFFSET)); + + /* append 'BOOT_IMAGE=' to parmline */ diff --git a/s390-tools-sles15sp2-03-zipl-correct-secure-boot-config-handling.patch b/s390-tools-sles15sp2-03-zipl-correct-secure-boot-config-handling.patch new file mode 100644 index 0000000..39dc9b7 --- /dev/null +++ b/s390-tools-sles15sp2-03-zipl-correct-secure-boot-config-handling.patch @@ -0,0 +1,187 @@ +Subject: [PATCH] [BZ 184396] zipl: correct secure boot config handling +From: Stefan Haberland + +Description: zipl: fix secure boot config handling +Symptom: The config file parsing for secure boot worked not as + it was expected to be. For example a config section + setting was not evaluated properly. + It is not possible to specify command line option -S + without other options. + Additionally the man page showed an invalid example. +Problem: The config file parsing was not implemented properly. +Solution: The hierarchy of the secure boot settings in the config + file is: + defaultboot > menu > section + Allow that --secure or -S is specified on command line + without the need to allow all options on the command + line. Also ensure that the command line option + overrules the config option and correctly ensure that + secure boot is only set for SCSI devices. + Fix man page example. +Reproduction: Run zipl with a secure= setting in a configuration + section or specify -S on command line. +Upstream-ID: 6f9337d1016e00f360cf4a81d39a42df5184b3a2 +Problem-ID: 184396 + +Upstream-Description: + + zipl: correct secure boot config handling + + The hierarchy of the secure boot settings in the config file should be: + + defaultboot > menu > section + + This patch implements this hierarchy and adds a check if a valid option is + specified and prints an error message otherwise. + + Signed-off-by: Stefan Haberland + Reviewed-by: Philipp Rudo + Signed-off-by: Jan Hoeppner + + +Signed-off-by: Stefan Haberland +--- + zipl/include/job.h | 1 + + zipl/include/zipl.h | 1 + + zipl/src/bootmap.c | 8 +++++++- + zipl/src/job.c | 29 ++++++++++++++++++++++++++--- + 4 files changed, 35 insertions(+), 4 deletions(-) + +--- a/zipl/include/job.h ++++ b/zipl/include/job.h +@@ -94,6 +94,7 @@ struct job_menu_entry { + char* name; + enum job_id id; + union job_menu_entry_data data; ++ int is_secure; + }; + + struct job_menu_data { +--- a/zipl/include/zipl.h ++++ b/zipl/include/zipl.h +@@ -57,6 +57,7 @@ + + #define MAX_DUMP_VOLUMES 32 + ++#define SECURE_BOOT_UNDEFINED -1 + #define SECURE_BOOT_DISABLED 0 + #define SECURE_BOOT_ENABLED 1 + #define SECURE_BOOT_AUTO 2 +--- a/zipl/src/bootmap.c ++++ b/zipl/src/bootmap.c +@@ -945,6 +945,7 @@ build_program_table(int fd, struct job_d + { + disk_blockptr_t* table; + int entries, component_header; ++ int is_secure; + int i; + int rc; + +@@ -1016,13 +1017,18 @@ build_program_table(int fd, struct job_d + component_header_ipl; + printf("\n"); + } ++ if (job->is_secure != SECURE_BOOT_UNDEFINED) ++ is_secure = job->is_secure; ++ else ++ is_secure = ++ job->data.menu.entry[i].is_secure; + rc = add_ipl_program(fd, + &job->data.menu.entry[i].data.ipl, + &table[job->data.menu.entry[i].pos], + verbose || job->command_line, + job->add_files, component_header, + info, &job->target, +- job->is_secure); ++ is_secure); + break; + case job_print_usage: + case job_print_version: +--- a/zipl/src/job.c ++++ b/zipl/src/job.c +@@ -119,6 +119,7 @@ get_command_line(int argc, char* argv[], + memset((void *) &cmdline, 0, sizeof(struct command_line)); + cmdline.type = section_invalid; + is_keyword = 0; ++ cmdline.is_secure = SECURE_BOOT_UNDEFINED; + /* Process options */ + do { + opt = getopt_long(argc, argv, option_string, options, NULL); +@@ -1055,6 +1056,21 @@ check_job_mvdump_data(struct job_mvdump_ + return 0; + } + ++static int ++check_secure_boot(struct job_data *job) ++{ ++ switch (job->is_secure) { ++ case SECURE_BOOT_UNDEFINED: ++ case SECURE_BOOT_DISABLED: ++ case SECURE_BOOT_ENABLED: ++ case SECURE_BOOT_AUTO: ++ return 0; ++ default: ++ error_reason("Invalid secure boot setting '%d'", ++ job->is_secure); ++ return -1; ++ } ++} + + static int + check_job_data(struct job_data* job) +@@ -1099,6 +1115,8 @@ check_job_data(struct job_data* job) + case job_mvdump: + rc = check_job_mvdump_data(&job->data.mvdump, job->name); + } ++ if (!rc) ++ rc = check_secure_boot(job); + return rc; + } + +@@ -1594,6 +1612,7 @@ get_menu_job(struct scan_token* scan, ch + sizeof(struct job_menu_entry) * job->data.menu.num); + /* Fill in data */ + current = 0; ++ job->data.menu.entry->is_secure = SECURE_BOOT_UNDEFINED; + for (i=index+1; (scan[i].id != scan_id_empty) && + (scan[i].id != scan_id_section_heading) && + (scan[i].id != scan_id_menu_heading); i++) { +@@ -1625,6 +1644,7 @@ get_menu_job(struct scan_token* scan, ch + if (temp_job == NULL) + return -1; + memset((void *) temp_job, 0, sizeof(struct job_data)); ++ temp_job->is_secure = SECURE_BOOT_UNDEFINED; + rc = get_job_from_section_data(data, temp_job, + job->data.menu.entry[current].name); + if (rc) { +@@ -1637,6 +1657,8 @@ get_menu_job(struct scan_token* scan, ch + job->data.menu.entry[current].id = job_ipl; + job->data.menu.entry[current].data.ipl = + temp_job->data.ipl; ++ job->data.menu.entry[current].is_secure = ++ temp_job->is_secure; + memset((void *) &temp_job->data.ipl, 0, + sizeof(struct job_ipl_data)); + break; +@@ -1874,6 +1896,7 @@ job_get(int argc, char* argv[], struct j + job->add_files = cmdline.add_files; + job->data.mvdump.force = cmdline.force; + job->dry_run = cmdline.dry_run; ++ job->is_secure = SECURE_BOOT_UNDEFINED; + /* Get job data from user input */ + if (cmdline.help) { + job->command_line = 1; +@@ -1892,10 +1915,10 @@ job_get(int argc, char* argv[], struct j + job_free(job); + return rc; + } +- if (cmdline.is_secure) ++ if (cmdline.is_secure != SECURE_BOOT_UNDEFINED) + job->is_secure = cmdline.is_secure; +- else +- job->is_secure = job->is_secure ? : SECURE_BOOT_AUTO; ++ else if (job->id != job_menu && job->is_secure == SECURE_BOOT_UNDEFINED) ++ job->is_secure = SECURE_BOOT_AUTO; + + /* Check job data for validity */ + rc = check_job_data(job); diff --git a/s390-tools-sles15sp2-03-zipl-remove-some-useless-__packed___-attributes.patch b/s390-tools-sles15sp2-03-zipl-remove-some-useless-__packed___-attributes.patch new file mode 100644 index 0000000..4deac13 --- /dev/null +++ b/s390-tools-sles15sp2-03-zipl-remove-some-useless-__packed___-attributes.patch @@ -0,0 +1,143 @@ +Subject: [PATCH] [FEAT VS1804] zipl: remove some useless __packed___ attributes +From: Marc Hartmayer + +Summary: genprotimg: Introduce new tool for the creation of PV images +Description: genprotimg takes a kernel, host-key documents, optionally an + initrd, optionally a file with the kernel command line, and it + generates a single, loadable image file. The image consists of a + concatenation of a plain text boot loader, the encrypted + components for kernel, initrd, and cmdline, and the + integrity-protected PV header, containing metadata necessary for + running the guest in PV mode. It's possible to use this image file + as a kernel for zIPL or for a direct kernel boot using QEMU. +Upstream-ID: 2227bb8330aea1368ba234ae6f24fe0b5779d67d +Problem-ID: VS1804 + +Upstream-Description: + + zipl: remove some useless __packed___ attributes + + The __packed__ attribute is not needed for these structures as they + don't need any padding to meet the size and alignment constraints + defined in the Linux for zSeries ABI. + + Reported by GCC 9.2.1 when building with '-Waddress-of-packed-member'. + + stage3.c: In function 'is_verified_address': + stage3.c:241:26: warning: taking address of packed member of 'struct ipl_rb_components' may result in an unaligned pointer value [-Waddress-of-packed-member] + 241 | for_each_rb_entry(comp, comps) { + | ^~~~~ + stage3.c:18:15: note: in definition of macro 'for_each_rb_entry' + 18 | for (entry = rb->entries; \ + | ^~ + CC zipl/boot/kdump3.o + CC zipl/boot/sclp_stage3.o + sclp_stage3.c: In function '__sclp_hsa_copy': + sclp_stage3.c:75:34: warning: converting a packed 'struct sdias_sccb' pointer (alignment 1) to a 'struct read_sccb' pointer (alignment 4096) may result in an unaligned pointer value [-Waddress-of-packed-member] + 75 | if (sclp_hsa_copy_wait((struct read_sccb *)sccb)) + | ^~~~~~~~~ + In file included from sclp_stage3.c:13: + sclp_stage3.h:43:8: note: defined here + 43 | struct sdias_sccb { + | ^~~~~~~~~~ + In file included from sclp_stage3.c:12: + sclp.h:149:8: note: defined here + 149 | struct read_sccb { + | ^~~~~~~~~ + sclp_stage3.c: In function 'sclp_hsa_get_size': + sclp_stage3.c:126:34: warning: converting a packed 'struct sdias_sccb' pointer (alignment 1) to a 'struct read_sccb' pointer (alignment 4096) may result in an unaligned pointer value [-Waddress-of-packed-member] + 126 | if (sclp_hsa_copy_wait((struct read_sccb *)sccb)) + | ^~~~~~~~~ + In file included from sclp_stage3.c:13: + sclp_stage3.h:43:8: note: defined here + 43 | struct sdias_sccb { + | ^~~~~~~~~~ + In file included from sclp_stage3.c:12: + sclp.h:149:8: note: defined here + 149 | struct read_sccb { + | ^~~~~~~~~ + + Signed-off-by: Marc Hartmayer + Reviewed-by: Stefan Haberland + Signed-off-by: Jan Höppner + + +Signed-off-by: Marc Hartmayer +--- + zipl/boot/sclp.h | 6 ++++-- + zipl/boot/sclp_stage3.h | 3 ++- + zipl/boot/stage3.h | 6 ++++-- + 3 files changed, 10 insertions(+), 5 deletions(-) + +--- a/zipl/boot/sclp.h ++++ b/zipl/boot/sclp.h +@@ -53,19 +53,21 @@ struct gds_subvector { + uint8_t key; + } __packed; + ++/* Structure must not have any padding */ + struct sccb_header { + uint16_t length; + uint8_t function_code; + uint8_t control_mask[3]; + uint16_t response_code; +-} __packed; ++}; + ++/* Structure must not have any padding */ + struct evbuf_header { + uint16_t length; + uint8_t type; + uint8_t flags; + uint16_t _reserved; +-} __packed; ++}; + + struct mto { + uint16_t length; +--- a/zipl/boot/sclp_stage3.h ++++ b/zipl/boot/sclp_stage3.h +@@ -40,10 +40,11 @@ struct sdias_evbuf { + uint16_t dbs; + } __packed; + ++/* Structure must not have any padding */ + struct sdias_sccb { + struct sccb_header header; + struct sdias_evbuf evbuf; +-} __packed; ++}; + + + int sclp_hsa_copy(void *, unsigned long, unsigned long); +--- a/zipl/boot/stage3.h ++++ b/zipl/boot/stage3.h +@@ -124,11 +124,12 @@ struct ipl_rl_hdr { + } __packed; + + /* IPL Report Block header */ ++/* Structure must not have any padding */ + struct ipl_rb_hdr { + uint32_t len; + uint8_t rbt; + uint8_t reserved1[11]; +-} __packed; ++}; + + /* IPL Report Block types */ + enum ipl_rbt { +@@ -162,12 +163,13 @@ struct ipl_rb_component_entry { + #define IPL_RB_COMPONENT_FLAG_SIGNED 0x80 + #define IPL_RB_COMPONENT_FLAG_VERIFIED 0x40 + ++/* Structure must not have any padding */ + struct ipl_rb_components { + uint32_t len; + uint8_t rbt; + uint8_t reserved1[11]; + struct ipl_rb_component_entry entries[]; +-} __packed; ++}; + + extern unsigned long long _parm_addr; /* address of parmline */ + extern unsigned long long _initrd_addr; /* address of initrd */ diff --git a/s390-tools-sles15sp2-04-zipl-Fix-entry-point-for-stand-alone-kdump.patch b/s390-tools-sles15sp2-04-zipl-Fix-entry-point-for-stand-alone-kdump.patch new file mode 100644 index 0000000..b7522c7 --- /dev/null +++ b/s390-tools-sles15sp2-04-zipl-Fix-entry-point-for-stand-alone-kdump.patch @@ -0,0 +1,95 @@ +Subject: [PATCH] [FEAT VS1804] zipl: Fix entry point for stand-alone kdump +From: Marc Hartmayer + +Summary: genprotimg: Introduce new tool for the creation of PV images +Description: genprotimg takes a kernel, host-key documents, optionally an + initrd, optionally a file with the kernel command line, and it + generates a single, loadable image file. The image consists of a + concatenation of a plain text boot loader, the encrypted + components for kernel, initrd, and cmdline, and the + integrity-protected PV header, containing metadata necessary for + running the guest in PV mode. It's possible to use this image file + as a kernel for zIPL or for a direct kernel boot using QEMU. +Upstream-ID: abe0ba7412f4398973235497754b05a199aec818 +Problem-ID: VS1804 + +Upstream-Description: + + zipl: Fix entry point for stand-alone kdump + + Currently zipl doesn't differentiate between the load address and the + entry point of an image, causing stage3 to strip away the entry point at + 0x10000 for stand-alone kdump. This breaks the kdump kernel as it jumps + to 0x10000 after the special handling needed for kdump has been + performed. + + Fix this by differentiating between the load address and the entry point + of an image. + + Fixes: d142fbd5 ("zipl: Do not strip kernel image IPL header") + Signed-off-by: Philipp Rudo + Reviewed-by: Stefan Haberland + Signed-off-by: Jan Höppner + + +Signed-off-by: Marc Hartmayer +--- + zipl/include/boot.h | 4 ++-- + zipl/src/boot.c | 10 +++++----- + zipl/src/bootmap.c | 2 +- + 3 files changed, 8 insertions(+), 8 deletions(-) + +--- a/zipl/include/boot.h ++++ b/zipl/include/boot.h +@@ -310,8 +310,8 @@ int boot_init_fba_stage1b(struct boot_fb + int boot_get_eckd_stage2(void** data, size_t* size, struct job_data* job); + int boot_get_stage3_parms(void **buffer, size_t *bytecount, address_t parm_addr, + address_t initrd_addr, size_t initrd_len, +- address_t load_addr, int extra_parm, uint16_t flags, +- size_t image_len); ++ address_t entry, int extra_parm, uint16_t flags, ++ address_t image_addr, size_t image_len); + int boot_get_tape_ipl(void** data, size_t* size, address_t parm_addr, + address_t initrd_addr, address_t image_addr); + int boot_get_tape_dump(void** data, size_t* size, uint64_t mem); +--- a/zipl/src/boot.c ++++ b/zipl/src/boot.c +@@ -79,14 +79,14 @@ boot_check_data(void) + int + boot_get_stage3_parms(void **buffer, size_t *bytecount, address_t parm_addr, + address_t initrd_addr, size_t initrd_len, +- address_t image_addr, int extra_parm, uint16_t flags, +- size_t image_len) ++ address_t entry, int extra_parm, uint16_t flags, ++ address_t image_addr, size_t image_len) + { + struct boot_stage3_params params; + void* data; + +- if (image_addr != (image_addr & PSW_ADDRESS_MASK)) { +- error_reason("Kernel image load address to high (31 bit " ++ if (entry != (entry & PSW_ADDRESS_MASK)) { ++ error_reason("Kernel image entry point to high (31 bit " + "addressing mode)"); + return -1; + } +@@ -99,7 +99,7 @@ boot_get_stage3_parms(void **buffer, siz + params.parm_addr = (uint64_t) parm_addr; + params.initrd_addr = (uint64_t) initrd_addr; + params.initrd_len = (uint64_t) initrd_len; +- params.load_psw = (uint64_t)(image_addr | PSW_LOAD); ++ params.load_psw = (uint64_t)(entry | PSW_LOAD); + params.extra_parm = (uint64_t) extra_parm; + params.flags = flags; + params.image_len = (uint64_t) image_len; +--- a/zipl/src/bootmap.c ++++ b/zipl/src/bootmap.c +@@ -646,7 +646,7 @@ add_ipl_program(int fd, struct job_ipl_d + ipl->is_kdump ? ipl->image_addr + 0x10 : + ipl->image_addr, + (info->type == disk_type_scsi) ? 0 : 1, +- flags, image_size); ++ flags, ipl->image_addr, image_size); + if (rc) { + free(table); + return rc; diff --git a/s390-tools-sles15sp2-04-zipl-fix-zipl.conf-man-page-example-for-secure-boot.patch b/s390-tools-sles15sp2-04-zipl-fix-zipl.conf-man-page-example-for-secure-boot.patch new file mode 100644 index 0000000..2582941 --- /dev/null +++ b/s390-tools-sles15sp2-04-zipl-fix-zipl.conf-man-page-example-for-secure-boot.patch @@ -0,0 +1,70 @@ +Subject: [PATCH] [BZ 184396] zipl: fix zipl.conf man page example for secure boot +From: Stefan Haberland + +Description: zipl: fix secure boot config handling +Symptom: The config file parsing for secure boot worked not as + it was expected to be. For example a config section + setting was not evaluated properly. + It is not possible to specify command line option -S + without other options. + Additionally the man page showed an invalid example. +Problem: The config file parsing was not implemented properly. +Solution: The hierarchy of the secure boot settings in the config + file is: + defaultboot > menu > section + Allow that --secure or -S is specified on command line + without the need to allow all options on the command + line. Also ensure that the command line option + overrules the config option and correctly ensure that + secure boot is only set for SCSI devices. + Fix man page example. +Reproduction: Run zipl with a secure= setting in a configuration + section or specify -S on command line. +Upstream-ID: 299fd2b7729f35c6fe3be18964f7e5e6a365f94d +Problem-ID: 184396 + +Upstream-Description: + + zipl: fix zipl.conf man page example for secure boot + + The secure= option is not supported in the defaultboot section when a + menu is used. It should be placed in the menu section in this case. + + Signed-off-by: Stefan Haberland + Signed-off-by: Jan Hoeppner + + +Signed-off-by: Stefan Haberland +--- + zipl/man/zipl.conf.5 | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/zipl/man/zipl.conf.5 ++++ b/zipl/man/zipl.conf.5 +@@ -82,8 +82,6 @@ below). + .br + defaultmenu = menu1 + .br +-secure = auto +-.br + + [linux] + .br +@@ -117,6 +115,8 @@ prompt = 1 + .br + timeout = 0 + .br ++secure = auto ++.br + .PP + + .B BootLoaderSpec configuration files +@@ -522,7 +522,7 @@ non-default memory location. + .B secure + = + .IR auto / 1 / 0 +-(configuration only) ++(configuration and menu) + .IP + .B Configuration section: + .br diff --git a/s390-tools-sles15sp2-05-zipl-Fix-dependency-generation-in-zipl-boot.patch b/s390-tools-sles15sp2-05-zipl-Fix-dependency-generation-in-zipl-boot.patch new file mode 100644 index 0000000..754114a --- /dev/null +++ b/s390-tools-sles15sp2-05-zipl-Fix-dependency-generation-in-zipl-boot.patch @@ -0,0 +1,76 @@ +Subject: [PATCH] [FEAT VS1804] zipl: Fix dependency generation in zipl/boot +From: Marc Hartmayer + +Summary: genprotimg: Introduce new tool for the creation of PV images +Description: genprotimg takes a kernel, host-key documents, optionally an + initrd, optionally a file with the kernel command line, and it + generates a single, loadable image file. The image consists of a + concatenation of a plain text boot loader, the encrypted + components for kernel, initrd, and cmdline, and the + integrity-protected PV header, containing metadata necessary for + running the guest in PV mode. It's possible to use this image file + as a kernel for zIPL or for a direct kernel boot using QEMU. +Upstream-ID: 121d5d80137f270e4828f457f717e9ab365f303b +Problem-ID: VS1804 + +Upstream-Description: + + zipl: Fix dependency generation in zipl/boot + + When adding new header from zipl/include to a .c file within zipl/boot + a compiler error appears + + stage3.c:16:10: fatal error: zipl.h: No such file or directory + #include "zipl.h" + ^~~~~~~~ + compilation terminated. + CC zipl/boot/stage3.o + + This is because the rule to generate dependencies (*.o.d) does not use + the CFLAGS_BOOT. Thus it cannot find the header and fails. Note this + only applies to the dependency generation, the actual build succeeds. + + To fix this rename the CFLAGS_BOOT to ALL_CFLAGS. Using ALL_CFLAGS + instead of e.g. ALL_CPPFLAGS is important to also overwrite flags given + on the commandline via OPT_FLAGS, e.g. + + make V=1 OPT_FLAGS="-D__FOO__" + + While at it also remove the unused and wrong '-D__ASSEMBLY__'. + + Fixes: 5a6605fe ("zipl: Ensure that boot loader CFLAGS are not overwritten") + Fixes: aa913b1e ("build process: Add automatic dependency generation") + Signed-off-by: Philipp Rudo + Reviewed-by: Stefan Haberland + Signed-off-by: Jan Höppner + + +Signed-off-by: Marc Hartmayer +--- + zipl/boot/Makefile | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/zipl/boot/Makefile ++++ b/zipl/boot/Makefile +@@ -1,7 +1,7 @@ + # Common definitions + include ../../common.mak + +-CFLAGS_BOOT = $(NO_PIE_CFLAGS) -Os -g -I../include -D__ASSEMBLY__ \ ++ALL_CFLAGS = $(NO_PIE_CFLAGS) -Os -g -I $(rootdir)/zipl/include \ + -DS390_TOOLS_RELEASE=$(S390_TOOLS_RELEASE) \ + -fno-builtin -ffreestanding -fno-asynchronous-unwind-tables \ + -fno-delete-null-pointer-checks \ +@@ -21,10 +21,10 @@ all: data.o data.h tape0.bin stage3.bin + %: %.S + + %.o: %.S +- $(CC) $(CFLAGS_BOOT) -c -o $@ $< ++ $(CC) $(ALL_CFLAGS) -c -o $@ $< + + %.o: %.c +- $(CC) $(CFLAGS_BOOT) -c -o $@ $< ++ $(CC) $(ALL_CFLAGS) -c -o $@ $< + + eckd2dump_sv.exec: \ + head.o stage2dump.o cio.o eckd2dump.o eckd2dump_sv.o \ diff --git a/s390-tools-sles15sp2-06-zipl-Make-use-of-__packed-macro.patch b/s390-tools-sles15sp2-06-zipl-Make-use-of-__packed-macro.patch new file mode 100644 index 0000000..58c67f8 --- /dev/null +++ b/s390-tools-sles15sp2-06-zipl-Make-use-of-__packed-macro.patch @@ -0,0 +1,349 @@ +Subject: [PATCH] [FEAT VS1804] zipl: Make use of __packed macro +From: Marc Hartmayer + +Summary: genprotimg: Introduce new tool for the creation of PV images +Description: genprotimg takes a kernel, host-key documents, optionally an + initrd, optionally a file with the kernel command line, and it + generates a single, loadable image file. The image consists of a + concatenation of a plain text boot loader, the encrypted + components for kernel, initrd, and cmdline, and the + integrity-protected PV header, containing metadata necessary for + running the guest in PV mode. It's possible to use this image file + as a kernel for zIPL or for a direct kernel boot using QEMU. +Upstream-ID: 0f7ed7d4fc86041a8646ce7abb615849e1298cca +Problem-ID: VS1804 + +Upstream-Description: + + zipl: Make use of __packed macro + + Make use of the pre-defined __packed macro throughout zipl. This + requires adding the global include dir to ALL_CFLAGS. + + Signed-off-by: Philipp Rudo + Reviewed-by: Stefan Haberland + Signed-off-by: Jan Höppner + + +Signed-off-by: Marc Hartmayer +--- + zipl/boot/Makefile | 2 - + zipl/boot/s390.h | 2 - + zipl/include/boot.h | 52 +++++++++++++++++++++++++------------------------ + zipl/include/bootmap.h | 4 ++- + zipl/src/bootmap.c | 5 ++-- + zipl/src/install.c | 3 +- + 6 files changed, 37 insertions(+), 31 deletions(-) + +--- a/zipl/boot/Makefile ++++ b/zipl/boot/Makefile +@@ -2,7 +2,7 @@ + include ../../common.mak + + ALL_CFLAGS = $(NO_PIE_CFLAGS) -Os -g -I $(rootdir)/zipl/include \ +- -DS390_TOOLS_RELEASE=$(S390_TOOLS_RELEASE) \ ++ -I $(rootdir)/include -DS390_TOOLS_RELEASE=$(S390_TOOLS_RELEASE) \ + -fno-builtin -ffreestanding -fno-asynchronous-unwind-tables \ + -fno-delete-null-pointer-checks \ + -fexec-charset=IBM1047 -m64 -mpacked-stack \ +--- a/zipl/boot/s390.h ++++ b/zipl/boot/s390.h +@@ -11,7 +11,7 @@ + #ifndef S390_H + #define S390_H + +-#include "../../include/lib/zt_common.h" ++#include "lib/zt_common.h" + #include "libc.h" + + #define __pa32(x) ((uint32_t)(unsigned long)(x)) +--- a/zipl/include/boot.h ++++ b/zipl/include/boot.h +@@ -14,6 +14,8 @@ + + #include + ++#include "lib/zt_common.h" ++ + #include "disk.h" + #include "job.h" + #include "zipl.h" +@@ -51,7 +53,7 @@ struct scsi_dump_sb { + uint64_t csum_offset; + uint64_t csum_size; + uint64_t csum; +-} __attribute((packed)); ++} __packed; + + #define SCSI_DUMP_SB_MAGIC 0x5a46435044554d50ULL; /* ZFCPDUMP */ + /* To avoid a csum entry of 0 a seed is used */ +@@ -63,7 +65,7 @@ struct scsi_dump_sb { + struct scsi_dump_param { + uint64_t block; + uint64_t reserved; +-} __attribute((packed)); ++} __packed; + /* ECKD dump parameter */ + + struct eckd_dump_param { +@@ -73,14 +75,14 @@ struct eckd_dump_param { + uint8_t num_heads; + uint8_t bpt; + char reserved[4]; +-} __attribute((packed, may_alias)); ++} __packed __may_alias; + + /* FBA dump parameter */ + + struct fba_dump_param { + uint64_t start_blk; + uint64_t blockct; +-} __attribute((packed)); ++} __packed; + + struct boot_info_bp_dump { + union { +@@ -89,7 +91,7 @@ struct boot_info_bp_dump { + struct scsi_dump_param scsi; + } param; + uint8_t unused[16]; +-} __attribute__ ((packed)); ++} __packed; + + /* + * Layout of block pointer for linear devices +@@ -101,7 +103,7 @@ struct linear_blockptr { + uint16_t size; + uint16_t blockct; + uint8_t reserved[4]; +-} __attribute((packed)); ++} __packed; + + /* + * Layout of block pointer for cylinder/head/sector devices +@@ -115,7 +117,7 @@ struct eckd_blockptr { + uint16_t size; + uint8_t blockct; + uint8_t reserved[8]; +-} __attribute((packed)); ++} __packed; + + struct boot_info_bp_ipl { + union { +@@ -123,7 +125,7 @@ struct boot_info_bp_ipl { + struct linear_blockptr lin; + } bm_ptr; + uint8_t unused[16]; +-} __attribute__ ((packed)); ++} __packed; + + struct boot_info { + char magic[4]; +@@ -135,7 +137,7 @@ struct boot_info { + struct boot_info_bp_dump dump; + struct boot_info_bp_ipl ipl; + } bp; +-} __attribute__ ((packed)); ++} __packed; + + struct boot_ccw0 { + uint8_t cmd; +@@ -144,21 +146,21 @@ struct boot_ccw0 { + uint8_t flags; + uint8_t pad; + uint16_t count; +-} __attribute__ ((packed)); ++} __packed; + + /* Boot data structures for FBA disks */ + + struct boot_fba_locread { + struct boot_ccw0 locate; + struct boot_ccw0 read; +-} __attribute__ ((packed)); ++} __packed; + + struct boot_fba_locdata { + uint8_t command; + uint8_t dummy; + uint16_t blockct; + uint32_t blocknr; +-} __attribute__ ((packed)); ++} __packed; + + struct boot_fba_stage0 { + uint64_t psw; +@@ -169,13 +171,13 @@ struct boot_fba_stage0 { + struct boot_fba_locdata locdata[2]; + uint64_t reserved[4]; + struct boot_info boot_info; +-} __attribute__ ((packed)); ++} __packed; + + struct boot_fba_stage1b { + struct boot_fba_locread locread[STAGE2_BLK_CNT_MAX]; + struct boot_fba_locdata locdata[STAGE2_BLK_CNT_MAX]; + uint8_t unused[448]; +-} __attribute__ ((packed)); ++} __packed; + + /* Boot data structures for ECKD disks */ + +@@ -184,14 +186,14 @@ struct boot_eckd_ccw1 { + uint8_t flags; + uint16_t count; + uint32_t address; +-} __attribute__ ((packed)); ++} __packed; + + struct boot_eckd_ssrt { + struct boot_ccw0 seek; + struct boot_ccw0 search; + struct boot_ccw0 tic; + struct boot_ccw0 read; +-} __attribute__ ((packed)); ++} __packed; + + struct boot_eckd_seekarg { + uint16_t pad; +@@ -199,32 +201,32 @@ struct boot_eckd_seekarg { + uint16_t head; + uint8_t sec; + uint8_t pad2; +-} __attribute__ ((packed)); ++} __packed; + + struct boot_eckd_cdl_stage0 { + uint64_t psw; + struct boot_ccw0 read; + struct boot_ccw0 tic; +-} __attribute__ ((packed)); ++} __packed; + + struct boot_eckd_ldl_stage0 { + uint64_t psw; + struct boot_ccw0 read_r0; + struct boot_ccw0 read_r1; +-} __attribute__ ((packed)); ++} __packed; + + struct boot_eckd_stage1 { + struct boot_eckd_ssrt ssrt[2]; + struct boot_ccw0 tic1b; + struct boot_eckd_seekarg seek[2]; + struct boot_info boot_info; +-} __attribute__ ((packed)); ++} __packed; + + struct boot_eckd_stage1b { + struct boot_eckd_ssrt ssrt[STAGE2_BLK_CNT_MAX]; + struct boot_eckd_seekarg seek[STAGE2_BLK_CNT_MAX]; + uint8_t unused[64]; +-} __attribute__ ((packed)); ++} __packed; + + /* Stage 2 boot menu parameter structure */ + +@@ -236,7 +238,7 @@ struct boot_stage2_params { + uint16_t banner; + uint16_t config[BOOT_MENU_ENTRIES + 1]; + uint64_t config_kdump; +-} __attribute__ ((packed)); ++} __packed; + + + /* Stage 3 bootloader parameter structure */ +@@ -251,7 +253,7 @@ struct boot_stage3_params { + uint16_t reserved[3]; + uint64_t image_len; + uint64_t image_addr; +-} __attribute__ ((packed)); ++} __packed; + + #define STAGE3_FLAG_SCSI 0x0001 + #define STAGE3_FLAG_KDUMP 0x0002 +@@ -275,7 +277,7 @@ struct mvdump_param { + uint8_t blocksize; + uint8_t bpt; + uint8_t num_heads; +-} __attribute__ ((packed)); ++} __packed; + + struct mvdump_parm_table { + uint64_t timestamp; +@@ -284,7 +286,7 @@ struct mvdump_parm_table { + uint8_t ssid[MAX_DUMP_VOLUMES]; + unsigned char reserved[512 - sizeof(uint64_t) - sizeof(uint16_t) - + (MAX_DUMP_VOLUMES * (sizeof(struct mvdump_param) + 1))]; +-} __attribute__ ((packed)); ++} __packed; + + void boot_get_dump_info(struct boot_info *boot_info, uint8_t dev_type, + void *param); +--- a/zipl/include/bootmap.h ++++ b/zipl/include/bootmap.h +@@ -12,6 +12,8 @@ + #ifndef BOOTMAP_H + #define BOOTMAP_H + ++#include "lib/zt_common.h" ++ + #include "disk.h" + #include "job.h" + #include "zipl.h" +@@ -23,7 +25,7 @@ struct signature_header { + uint8_t format; + uint8_t reserved[3]; + uint32_t length; +-} __attribute((packed)); ++} __packed; + + typedef union { + uint64_t load_address; +--- a/zipl/src/bootmap.c ++++ b/zipl/src/bootmap.c +@@ -18,6 +18,7 @@ + #include + #include + ++#include "lib/zt_common.h" + #include "lib/util_part.h" + #include "lib/util_path.h" + +@@ -223,7 +224,7 @@ struct component_entry { + uint8_t data[23]; + uint8_t type; + component_data compdat; +-} __attribute((packed)); ++} __packed; + + typedef enum { + component_execute = 0x01, +@@ -263,7 +264,7 @@ struct component_header { + uint8_t magic[4]; + uint8_t type; + uint8_t reserved[27]; +-} __attribute((packed)); ++} __packed; + + typedef enum { + component_header_ipl = 0x00, +--- a/zipl/src/install.c ++++ b/zipl/src/install.c +@@ -23,6 +23,7 @@ + #include + #include + ++#include "lib/zt_common.h" + #include "lib/util_sys.h" + + #include "boot.h" +@@ -89,7 +90,7 @@ update_scsi_mbr(void* bootblock, disk_bl + uint8_t program_table_pointer[16]; + uint8_t reserved2[0x50]; + struct boot_info boot_info; +- } __attribute__ ((packed))* mbr; ++ } __packed* mbr; + struct scsi_dump_param param; + void* buffer; + diff --git a/s390-tools-sles15sp2-07-zipl-define-__section-macro-and-make-use-of-it.patch b/s390-tools-sles15sp2-07-zipl-define-__section-macro-and-make-use-of-it.patch new file mode 100644 index 0000000..605ca13 --- /dev/null +++ b/s390-tools-sles15sp2-07-zipl-define-__section-macro-and-make-use-of-it.patch @@ -0,0 +1,188 @@ +Subject: [PATCH] [FEAT VS1804] zipl: define __section macro and make use of it +From: Marc Hartmayer + +Summary: genprotimg: Introduce new tool for the creation of PV images +Description: genprotimg takes a kernel, host-key documents, optionally an + initrd, optionally a file with the kernel command line, and it + generates a single, loadable image file. The image consists of a + concatenation of a plain text boot loader, the encrypted + components for kernel, initrd, and cmdline, and the + integrity-protected PV header, containing metadata necessary for + running the guest in PV mode. It's possible to use this image file + as a kernel for zIPL or for a direct kernel boot using QEMU. +Upstream-ID: 154734efc7ffeb1e51dd2be62561a364fdc6117c +Problem-ID: VS1804 + +Upstream-Description: + + zipl: define __section macro and make use of it + + Signed-off-by: Philipp Rudo + Reviewed-by: Stefan Haberland + Signed-off-by: Jan Höppner + + +Signed-off-by: Marc Hartmayer +--- + include/lib/zt_common.h | 1 + + zipl/boot/eckd2dump_mv.c | 8 ++++---- + zipl/boot/eckd2dump_sv.c | 5 +++-- + zipl/boot/fba2dump.c | 4 ++-- + zipl/boot/stage2.c | 4 +++- + zipl/boot/stage2dump.c | 5 +++-- + zipl/boot/stage2dump.h | 3 +-- + zipl/boot/tape2dump.c | 4 +++- + 8 files changed, 20 insertions(+), 14 deletions(-) + +--- a/include/lib/zt_common.h ++++ b/include/lib/zt_common.h +@@ -31,6 +31,7 @@ + #define __packed __attribute__((packed)) + #define __aligned(x) __attribute__((aligned(x))) + #define __may_alias __attribute__((may_alias)) ++#define __section(x) __attribute__((__section__(#x))) + + typedef unsigned long long u64; + typedef signed long long s64; +--- a/zipl/boot/eckd2dump_mv.c ++++ b/zipl/boot/eckd2dump_mv.c +@@ -9,6 +9,8 @@ + * it under the terms of the MIT license. See LICENSE for details. + */ + ++#include "lib/zt_common.h" ++ + #include "eckd2dump.h" + #include "error.h" + #include "stage2dump.h" +@@ -19,8 +21,7 @@ + /* + * Magic number at start of dump record + */ +-uint64_t magic __attribute__((section(".stage2.head"))) +- = 0x584d554c54363401ULL; /* XMULT64, version 1 */ ++uint64_t __section(.stage2.head) magic = 0x584d554c54363401ULL; /* XMULT64, version 1 */ + + /* + * Parameter format for ECKD MV dumper (13 bytes): +@@ -59,8 +60,7 @@ struct mvdump_parm_table { + (MAX_DUMP_VOLUMES * (sizeof(struct mvdump_param) + 1))]; + } __packed; + +-static struct mvdump_parm_table mvdump_table +- __attribute__((section(".eckd2dump_mv.tail"))); ++static struct mvdump_parm_table __section(.eckd2dump_mv.tail) mvdump_table; + + static int volnr_current; + +--- a/zipl/boot/eckd2dump_sv.c ++++ b/zipl/boot/eckd2dump_sv.c +@@ -9,6 +9,8 @@ + * it under the terms of the MIT license. See LICENSE for details. + */ + ++#include "lib/zt_common.h" ++ + #include "eckd2dump.h" + #include "error.h" + #include "stage2dump.h" +@@ -16,8 +18,7 @@ + /* + * Magic number at start of dump record + */ +-uint64_t magic __attribute__((section(".stage2.head"))) = +- 0x5845434b44363401ULL; /* "XECKD64", version 1 */ ++uint64_t __section(.stage2.head) magic = 0x5845434b44363401ULL; /* "XECKD64", version 1 */ + + /* + * ECKD parameter block passed by zipl +--- a/zipl/boot/fba2dump.c ++++ b/zipl/boot/fba2dump.c +@@ -9,6 +9,7 @@ + * it under the terms of the MIT license. See LICENSE for details. + */ + ++#include "lib/zt_common.h" + #include "error.h" + #include "fba.h" + #include "stage2dump.h" +@@ -20,8 +21,7 @@ + /* + * Magic number at start of dump record + */ +-uint64_t magic __attribute__((section(".stage2.head"))) +- = 0x5844464241363401ULL; /* XDFBA64, version 1 */ ++uint64_t __section(.stage2.head) magic = 0x5844464241363401ULL; /* XDFBA64, version 1 */ + + /* + * FBA dump device partition specification +--- a/zipl/boot/stage2.c ++++ b/zipl/boot/stage2.c +@@ -9,6 +9,8 @@ + * it under the terms of the MIT license. See LICENSE for details. + */ + ++#include "lib/zt_common.h" ++ + #include "error.h" + #include "libc.h" + #include "menu.h" +@@ -141,4 +143,4 @@ void panic_notify(unsigned long UNUSED(r + { + } + +-uint64_t stage2_head __attribute__((section(".stage2.head"))); ++uint64_t __section(.stage2.head) stage2_head; +--- a/zipl/boot/stage2dump.c ++++ b/zipl/boot/stage2dump.c +@@ -11,6 +11,8 @@ + + #include + ++#include "lib/zt_common.h" ++ + #include "error.h" + #include "sclp.h" + #include "stage2dump.h" +@@ -34,8 +36,7 @@ struct ipib_info { + /* + * Tail parameters + */ +-struct stage2dump_parm_tail parm_tail +- __attribute__ ((section(".stage2dump.tail"))) = { ++struct stage2dump_parm_tail parm_tail = { + .mem_upper_limit = 0xffffffffffffffffULL, + }; + +--- a/zipl/boot/stage2dump.h ++++ b/zipl/boot/stage2dump.h +@@ -28,8 +28,7 @@ struct stage2dump_parm_tail { + uint64_t mem_upper_limit; + } __packed; + +-extern struct stage2dump_parm_tail parm_tail +- __attribute__ ((section(".stage2dump.tail"))); ++extern struct stage2dump_parm_tail __section(.stage2dump.tail) parm_tail; + + /* + * S390 dump format defines +--- a/zipl/boot/tape2dump.c ++++ b/zipl/boot/tape2dump.c +@@ -9,6 +9,8 @@ + * it under the terms of the MIT license. See LICENSE for details. + */ + ++#include "lib/zt_common.h" ++ + #include "cio.h" + #include "error.h" + #include "libc.h" +@@ -33,7 +35,7 @@ struct tape_head { + uint64_t ccw2; + } __packed; + +-struct tape_head tape_head __attribute__((section(".stage2.head"))) = { ++struct tape_head __section(.stage2.head) tape_head = { + .psw = 0x0008000080002018ULL, /* Start code at 0x2018 */ + .ccw1 = 0x0700000060000001ULL, /* Rewind ccw */ + .ccw2 = 0x0200200020003000ULL, /* CCW to load dump tool to 0x2000 */ diff --git a/s390-tools-sles15sp2-08-zipl-Make-use-of-__noreturn-macro.patch b/s390-tools-sles15sp2-08-zipl-Make-use-of-__noreturn-macro.patch new file mode 100644 index 0000000..f4716ef --- /dev/null +++ b/s390-tools-sles15sp2-08-zipl-Make-use-of-__noreturn-macro.patch @@ -0,0 +1,61 @@ +Subject: [PATCH] [FEAT VS1804] zipl: Make use of __noreturn macro +From: Marc Hartmayer + +Summary: genprotimg: Introduce new tool for the creation of PV images +Description: genprotimg takes a kernel, host-key documents, optionally an + initrd, optionally a file with the kernel command line, and it + generates a single, loadable image file. The image consists of a + concatenation of a plain text boot loader, the encrypted + components for kernel, initrd, and cmdline, and the + integrity-protected PV header, containing metadata necessary for + running the guest in PV mode. It's possible to use this image file + as a kernel for zIPL or for a direct kernel boot using QEMU. +Upstream-ID: 86856f98dbe3f68e34b91b58e9fc92f7cdc8a0d4 +Problem-ID: VS1804 + +Upstream-Description: + + zipl: Make use of __noreturn macro + + Signed-off-by: Philipp Rudo + Reviewed-by: Stefan Haberland + Signed-off-by: Jan Höppner + + +Signed-off-by: Marc Hartmayer +--- + zipl/boot/libc.c | 4 +++- + zipl/boot/libc.h | 2 +- + 2 files changed, 4 insertions(+), 2 deletions(-) + +--- a/zipl/boot/libc.c ++++ b/zipl/boot/libc.c +@@ -11,6 +11,8 @@ + + #include + ++#include "lib/zt_common.h" ++ + #include "error.h" + #include "libc.h" + #include "sclp.h" +@@ -511,7 +513,7 @@ void initialize(void) + /* + * Load disabled wait PSW with reason code in address field + */ +-void libc_stop(unsigned long reason) ++void __noreturn libc_stop(unsigned long reason) + { + struct psw_t psw; + +--- a/zipl/boot/libc.h ++++ b/zipl/boot/libc.h +@@ -60,7 +60,7 @@ char *strcpy(char *, const char *); + unsigned long get_zeroed_page(void); + void free_page(unsigned long); + void initialize(void); +-void libc_stop(unsigned long) __attribute__((noreturn)); ++void libc_stop(unsigned long); + void start(void); + void pgm_check_handler(void); + void pgm_check_handler_fn(void); diff --git a/s390-tools-sles15sp2-09-zipl-Define-__noinline-macro-and-make-use-of-it.patch b/s390-tools-sles15sp2-09-zipl-Define-__noinline-macro-and-make-use-of-it.patch new file mode 100644 index 0000000..4dee5d7 --- /dev/null +++ b/s390-tools-sles15sp2-09-zipl-Define-__noinline-macro-and-make-use-of-it.patch @@ -0,0 +1,66 @@ +Subject: [PATCH] [FEAT VS1804] zipl: Define __noinline macro and make use of it +From: Marc Hartmayer + +Summary: genprotimg: Introduce new tool for the creation of PV images +Description: genprotimg takes a kernel, host-key documents, optionally an + initrd, optionally a file with the kernel command line, and it + generates a single, loadable image file. The image consists of a + concatenation of a plain text boot loader, the encrypted + components for kernel, initrd, and cmdline, and the + integrity-protected PV header, containing metadata necessary for + running the guest in PV mode. It's possible to use this image file + as a kernel for zIPL or for a direct kernel boot using QEMU. +Upstream-ID: 5eace91ee7bd76b8ab44291299ac313c87c9ecb8 +Problem-ID: VS1804 + +Upstream-Description: + + zipl: Define __noinline macro and make use of it + + Signed-off-by: Philipp Rudo + Reviewed-by: Stefan Haberland + Signed-off-by: Jan Höppner + + +Signed-off-by: Marc Hartmayer +--- + include/lib/zt_common.h | 1 + + libutil/util_panic_example.c | 2 +- + zipl/boot/libc.c | 2 +- + 3 files changed, 3 insertions(+), 2 deletions(-) + +--- a/include/lib/zt_common.h ++++ b/include/lib/zt_common.h +@@ -32,6 +32,7 @@ + #define __aligned(x) __attribute__((aligned(x))) + #define __may_alias __attribute__((may_alias)) + #define __section(x) __attribute__((__section__(#x))) ++#define __noinline __attribute__((__noinline__)) + + typedef unsigned long long u64; + typedef signed long long s64; +--- a/libutil/util_panic_example.c ++++ b/libutil/util_panic_example.c +@@ -15,10 +15,10 @@ + #include + #include + ++#include "lib/zt_common.h" + #include "lib/util_panic.h" + + /* Make functions noinline to have a nice backtrace */ +-#define __noinline __attribute__((noinline)) + + /* + * Test util_panic() +--- a/zipl/boot/libc.c ++++ b/zipl/boot/libc.c +@@ -473,7 +473,7 @@ void pgm_check_handler_fn(void) + libc_stop(psw_old->addr); + } + +-__attribute__ ((noinline)) void load_wait_psw(uint64_t psw_mask, struct psw_t *psw) ++void __noinline load_wait_psw(uint64_t psw_mask, struct psw_t *psw) + { + struct psw_t wait_psw = { .mask = psw_mask, .addr = 0 }; + struct psw_t old_psw, *wait_psw_ptr = &wait_psw; diff --git a/s390-tools-sles15sp2-10-zipl-stage3-Mark-start_kernel-__noreturn.patch b/s390-tools-sles15sp2-10-zipl-stage3-Mark-start_kernel-__noreturn.patch new file mode 100644 index 0000000..c3c9b19 --- /dev/null +++ b/s390-tools-sles15sp2-10-zipl-stage3-Mark-start_kernel-__noreturn.patch @@ -0,0 +1,49 @@ +Subject: [PATCH] [FEAT VS1804] zipl/stage3: Mark start_kernel __noreturn +From: Marc Hartmayer + +Summary: genprotimg: Introduce new tool for the creation of PV images +Description: genprotimg takes a kernel, host-key documents, optionally an + initrd, optionally a file with the kernel command line, and it + generates a single, loadable image file. The image consists of a + concatenation of a plain text boot loader, the encrypted + components for kernel, initrd, and cmdline, and the + integrity-protected PV header, containing metadata necessary for + running the guest in PV mode. It's possible to use this image file + as a kernel for zIPL or for a direct kernel boot using QEMU. +Upstream-ID: edfb6a03d862e332223eda02be46109be12c0a4e +Problem-ID: VS1804 + +Upstream-Description: + + zipl/stage3: Mark start_kernel __noreturn + + Signed-off-by: Philipp Rudo + Reviewed-by: Stefan Haberland + Signed-off-by: Jan Höppner + + +Signed-off-by: Marc Hartmayer +--- + zipl/boot/stage3.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/zipl/boot/stage3.c ++++ b/zipl/boot/stage3.c +@@ -175,8 +175,7 @@ static void ebcdic_to_ascii(unsigned cha + target[i] = ebc[source[i]]; + } + +-static void +-start_kernel(void) ++static inline void __noreturn start_kernel(void) + { + struct psw_t *psw = &S390_lowcore.program_new_psw; + unsigned long addr, code; +@@ -199,6 +198,7 @@ start_kernel(void) + : [addr] "=&d" (addr), + [code] "+&d" (code) + : [psw] "a" (psw) ); ++ while (1); + } + + unsigned int diff --git a/s390-tools-sles15sp2-11-zipl-sclp-Remove-duplicate-macros.patch b/s390-tools-sles15sp2-11-zipl-sclp-Remove-duplicate-macros.patch new file mode 100644 index 0000000..f97f970 --- /dev/null +++ b/s390-tools-sles15sp2-11-zipl-sclp-Remove-duplicate-macros.patch @@ -0,0 +1,41 @@ +Subject: [PATCH] [FEAT VS1804] zipl/sclp: Remove duplicate macros +From: Marc Hartmayer + +Summary: genprotimg: Introduce new tool for the creation of PV images +Description: genprotimg takes a kernel, host-key documents, optionally an + initrd, optionally a file with the kernel command line, and it + generates a single, loadable image file. The image consists of a + concatenation of a plain text boot loader, the encrypted + components for kernel, initrd, and cmdline, and the + integrity-protected PV header, containing metadata necessary for + running the guest in PV mode. It's possible to use this image file + as a kernel for zIPL or for a direct kernel boot using QEMU. +Upstream-ID: b2ae5a91ac16c5facb892dedc2dcb268eff07edf +Problem-ID: VS1804 + +Upstream-Description: + + zipl/sclp: Remove duplicate macros + + Signed-off-by: Philipp Rudo + Reviewed-by: Stefan Haberland + Signed-off-by: Jan Höppner + + +Signed-off-by: Marc Hartmayer +--- + zipl/boot/sclp_stage3.h | 3 --- + 1 file changed, 3 deletions(-) + +--- a/zipl/boot/sclp_stage3.h ++++ b/zipl/boot/sclp_stage3.h +@@ -17,9 +17,6 @@ + #define SDIAS_EVSTATE_ALL_STORED 0x00 + #define SDIAS_EVSTATE_PART_STORED 0x10 + +-#define SDIAS_EVSTATE_ALL_STORED 0x00 +-#define SDIAS_EVSTATE_PART_STORED 0x10 +- + struct sdias_evbuf { + struct evbuf_header header; + uint8_t event_qual; diff --git a/s390-tools-sles15sp2-12-zipl-Make-address-size-mask-macros-UL.patch b/s390-tools-sles15sp2-12-zipl-Make-address-size-mask-macros-UL.patch new file mode 100644 index 0000000..d8463f4 --- /dev/null +++ b/s390-tools-sles15sp2-12-zipl-Make-address-size-mask-macros-UL.patch @@ -0,0 +1,116 @@ +Subject: [PATCH] [FEAT VS1804] zipl: Make address/size/mask macros UL +From: Marc Hartmayer + +Summary: genprotimg: Introduce new tool for the creation of PV images +Description: genprotimg takes a kernel, host-key documents, optionally an + initrd, optionally a file with the kernel command line, and it + generates a single, loadable image file. The image consists of a + concatenation of a plain text boot loader, the encrypted + components for kernel, initrd, and cmdline, and the + integrity-protected PV header, containing metadata necessary for + running the guest in PV mode. It's possible to use this image file + as a kernel for zIPL or for a direct kernel boot using QEMU. +Upstream-ID: ea14f5471c6fbc9a8a407aa33324db39082b4689 +Problem-ID: VS1804 + +Upstream-Description: + + zipl: Make address/size/mask macros UL + + While at it also fix some white space damages. + + Signed-off-by: Philipp Rudo + Reviewed-by: Stefan Haberland + Signed-off-by: Jan Höppner + + +Signed-off-by: Marc Hartmayer +--- + zipl/boot/stage3.h | 18 +++++++++--------- + zipl/include/zipl.h | 36 ++++++++++++++++++------------------ + 2 files changed, 27 insertions(+), 27 deletions(-) + +--- a/zipl/boot/stage3.h ++++ b/zipl/boot/stage3.h +@@ -15,12 +15,12 @@ + #include "libc.h" + #include "s390.h" + +-#define IPL_DEVICE 0x10404 +-#define INITRD_START 0x10408 +-#define INITRD_SIZE 0x10410 +-#define OLDMEM_BASE 0x10418 +-#define OLDMEM_SIZE 0x10420 +-#define COMMAND_LINE 0x10480 ++#define IPL_DEVICE 0x10404UL ++#define INITRD_START 0x10408UL ++#define INITRD_SIZE 0x10410UL ++#define OLDMEM_BASE 0x10418UL ++#define OLDMEM_SIZE 0x10420UL ++#define COMMAND_LINE 0x10480UL + #define COMMAND_LINE_SIZE 896 + #define COMMAND_LINE_EXTRA 0xE000 + +@@ -30,11 +30,11 @@ + #define IPL_FLAG_SECURE 0x40 + + #define DEFAULT_IMAGE_ADDR 0x10000 +-#define DEFAULT_PSW_LOAD 0x0008000080010000L +-#define PSW_ADDR_MASK 0x000000007FFFFFFFL ++#define DEFAULT_PSW_LOAD 0x0008000080010000UL ++#define PSW_ADDR_MASK 0x000000007FFFFFFFUL + #define KERNEL_HEADER_SIZE 65536 + +-#define UNSPECIFIED_ADDRESS -1ULL ++#define UNSPECIFIED_ADDRESS -1UL + + + /* IPL Parameter List header */ +--- a/zipl/include/zipl.h ++++ b/zipl/include/zipl.h +@@ -19,27 +19,27 @@ + #define ZIPL_MAGIC_SIZE 4 + #define DISK_LAYOUT_ID 0x00000001 + +-#define ZIPL_STAGE2_LOAD_ADDRESS 0x2000 +-#define ZIPL_STAGE3_ENTRY_ADDRESS 0xa000LL +-#define DEFAULT_IMAGE_ADDRESS 0x10000LL +-#define KDUMP_IMAGE_ADDRESS 0x10010LL +-#define DEFAULT_STAGE3_ADDRESS 0xa000LL +-#define DEFAULT_STAGE3_PARAMS_ADDRESS 0x9000LL +-#define MINIMUM_ADDRESS 0x10000LL +-#define ADDRESS_LIMIT 0x80000000LL ++#define ZIPL_STAGE2_LOAD_ADDRESS 0x2000UL ++#define ZIPL_STAGE3_ENTRY_ADDRESS 0xa000UL ++#define DEFAULT_IMAGE_ADDRESS 0x10000UL ++#define KDUMP_IMAGE_ADDRESS 0x10010UL ++#define DEFAULT_STAGE3_ADDRESS 0xa000UL ++#define DEFAULT_STAGE3_PARAMS_ADDRESS 0x9000UL ++#define MINIMUM_ADDRESS 0x10000UL ++#define ADDRESS_LIMIT 0x80000000UL + #define ADDRESS_LIMIT_KDUMP 0x2000000UL /* HSA size: 32 MiB */ +-#define UNSPECIFIED_ADDRESS -1ULL +-#define MAXIMUM_PARMLINE_SIZE 0x380 +-#define MAXIMUM_PHYSICAL_BLOCKSIZE 0x1000 ++#define UNSPECIFIED_ADDRESS -1UL ++#define MAXIMUM_PARMLINE_SIZE 0x380UL ++#define MAXIMUM_PHYSICAL_BLOCKSIZE 0x1000UL + +-#define STAGE3_HEAP_SIZE 0x4000 +-#define STAGE3_HEAP_ADDRESS 0x2000 +-#define STAGE3_STACK_SIZE 0x1000 +-#define STAGE3_STACK_ADDRESS 0xF000 ++#define STAGE3_HEAP_SIZE 0x4000UL ++#define STAGE3_HEAP_ADDRESS 0x2000UL ++#define STAGE3_STACK_SIZE 0x1000UL ++#define STAGE3_STACK_ADDRESS 0xF000UL + +-#define PSW_ADDRESS_MASK 0x000000007fffffffLL +-#define PSW_LOAD 0x0008000080000000LL +-#define PSW_DISABLED_WAIT 0x000a000000000000LL ++#define PSW_ADDRESS_MASK 0x000000007fffffffUL ++#define PSW_LOAD 0x0008000080000000UL ++#define PSW_DISABLED_WAIT 0x000a000000000000UL + + #define BOOTMAP_FILENAME "bootmap" + #define BOOTMAP_TEMPLATE_FILENAME "bootmap_temp.XXXXXX" diff --git a/s390-tools-sles15sp2-13-zipl-libc-Use-stdint.h-instead-of-self-defined-macro.patch b/s390-tools-sles15sp2-13-zipl-libc-Use-stdint.h-instead-of-self-defined-macro.patch new file mode 100644 index 0000000..26ace63 --- /dev/null +++ b/s390-tools-sles15sp2-13-zipl-libc-Use-stdint.h-instead-of-self-defined-macro.patch @@ -0,0 +1,52 @@ +Subject: [PATCH] [FEAT VS1804] zipl/libc: Use stdint.h instead of self defined macros +From: Marc Hartmayer + +Summary: genprotimg: Introduce new tool for the creation of PV images +Description: genprotimg takes a kernel, host-key documents, optionally an + initrd, optionally a file with the kernel command line, and it + generates a single, loadable image file. The image consists of a + concatenation of a plain text boot loader, the encrypted + components for kernel, initrd, and cmdline, and the + integrity-protected PV header, containing metadata necessary for + running the guest in PV mode. It's possible to use this image file + as a kernel for zIPL or for a direct kernel boot using QEMU. +Upstream-ID: 8face3e63ed88443392bcbcd93cc0b5e29b40069 +Problem-ID: VS1804 + +Upstream-Description: + + zipl/libc: Use stdint.h instead of self defined macros + + Signed-off-by: Philipp Rudo + Reviewed-by: Stefan Haberland + Signed-off-by: Jan Höppner + + +Signed-off-by: Marc Hartmayer +--- + zipl/boot/libc.h | 7 ++----- + 1 file changed, 2 insertions(+), 5 deletions(-) + +--- a/zipl/boot/libc.h ++++ b/zipl/boot/libc.h +@@ -11,6 +11,8 @@ + #ifndef LIBC_H + #define LIBC_H + ++#include ++ + #define NULL ((void *) 0) + + #define EPERM 1 /* Operation not permitted */ +@@ -42,11 +44,6 @@ + #define MIB (1024ULL * 1024) + #define LINE_LENGTH 80 /* max line length printed by printf */ + +-typedef unsigned long long uint64_t; +-typedef unsigned int uint32_t; +-typedef unsigned short uint16_t; +-typedef unsigned char uint8_t; +- + void printf(const char *, ...); + void snprintf(char *buf, unsigned long size, const char *fmt, ...); + void *memcpy(void *, const void *, unsigned long); diff --git a/s390-tools-sles15sp2-14-zipl-Consolidate-IMAGE-macros.patch b/s390-tools-sles15sp2-14-zipl-Consolidate-IMAGE-macros.patch new file mode 100644 index 0000000..70ae946 --- /dev/null +++ b/s390-tools-sles15sp2-14-zipl-Consolidate-IMAGE-macros.patch @@ -0,0 +1,199 @@ +Subject: [PATCH] [FEAT VS1804] zipl: Consolidate IMAGE macros +From: Marc Hartmayer + +Summary: genprotimg: Introduce new tool for the creation of PV images +Description: genprotimg takes a kernel, host-key documents, optionally an + initrd, optionally a file with the kernel command line, and it + generates a single, loadable image file. The image consists of a + concatenation of a plain text boot loader, the encrypted + components for kernel, initrd, and cmdline, and the + integrity-protected PV header, containing metadata necessary for + running the guest in PV mode. It's possible to use this image file + as a kernel for zIPL or for a direct kernel boot using QEMU. +Upstream-ID: cb614ed1ee61f05fb521a7e3ac0d27eb2eb45672 +Problem-ID: VS1804 + +Upstream-Description: + + zipl: Consolidate IMAGE macros + + Combine the different macros for 0x10000 and use a consistent naming + schema. + + Signed-off-by: Philipp Rudo + Reviewed-by: Stefan Haberland + Signed-off-by: Jan Höppner + + +Signed-off-by: Marc Hartmayer +--- + zipl/boot/stage3.c | 7 ++++--- + zipl/boot/stage3.h | 2 -- + zipl/include/zipl.h | 8 +++++--- + zipl/src/bootmap.c | 8 ++++---- + zipl/src/job.c | 17 +++++++++-------- + 5 files changed, 22 insertions(+), 20 deletions(-) + +--- a/zipl/boot/stage3.c ++++ b/zipl/boot/stage3.c +@@ -13,6 +13,7 @@ + #include "s390.h" + #include "stage3.h" + #include "error.h" ++#include "zipl.h" + + #define for_each_rb_entry(entry, rb) \ + for (entry = rb->entries; \ +@@ -272,7 +273,7 @@ void start(void) + * verified component. If it is not IPL is aborted. + */ + if (secure_boot_enabled()) { +- if (_image_addr != DEFAULT_IMAGE_ADDR || ++ if (_image_addr != IMAGE_LOAD_ADDRESS || + _load_psw != DEFAULT_PSW_LOAD) + panic(ESECUREBOOT, "%s", msg_sipl_inval); + +@@ -283,8 +284,8 @@ void start(void) + * cut the kernel header + */ + memmove((void *)_image_addr, +- (void *)_image_addr + KERNEL_HEADER_SIZE, +- _image_len - KERNEL_HEADER_SIZE); ++ (void *)_image_addr + IMAGE_LOAD_ADDRESS, ++ _image_len - IMAGE_LOAD_ADDRESS); + + /* store subchannel ID into low core and into new kernel space */ + subchannel_id = S390_lowcore.subchannel_id; +--- a/zipl/boot/stage3.h ++++ b/zipl/boot/stage3.h +@@ -29,10 +29,8 @@ + + #define IPL_FLAG_SECURE 0x40 + +-#define DEFAULT_IMAGE_ADDR 0x10000 + #define DEFAULT_PSW_LOAD 0x0008000080010000UL + #define PSW_ADDR_MASK 0x000000007FFFFFFFUL +-#define KERNEL_HEADER_SIZE 65536 + + #define UNSPECIFIED_ADDRESS -1UL + +--- a/zipl/include/zipl.h ++++ b/zipl/include/zipl.h +@@ -19,13 +19,15 @@ + #define ZIPL_MAGIC_SIZE 4 + #define DISK_LAYOUT_ID 0x00000001 + ++#define IMAGE_ENTRY 0x10000UL ++#define IMAGE_ENTRY_KDUMP 0x10010UL ++ + #define ZIPL_STAGE2_LOAD_ADDRESS 0x2000UL + #define ZIPL_STAGE3_ENTRY_ADDRESS 0xa000UL +-#define DEFAULT_IMAGE_ADDRESS 0x10000UL +-#define KDUMP_IMAGE_ADDRESS 0x10010UL + #define DEFAULT_STAGE3_ADDRESS 0xa000UL + #define DEFAULT_STAGE3_PARAMS_ADDRESS 0x9000UL +-#define MINIMUM_ADDRESS 0x10000UL ++#define IMAGE_LOAD_ADDRESS IMAGE_ENTRY ++ + #define ADDRESS_LIMIT 0x80000000UL + #define ADDRESS_LIMIT_KDUMP 0x2000000UL /* HSA size: 32 MiB */ + #define UNSPECIFIED_ADDRESS -1UL +--- a/zipl/src/bootmap.c ++++ b/zipl/src/bootmap.c +@@ -644,8 +644,8 @@ add_ipl_program(int fd, struct job_ipl_d + rc = boot_get_stage3_parms(&stage3_params, &stage3_params_size, + ipl->parm_addr, ipl->ramdisk_addr, + ramdisk_size, +- ipl->is_kdump ? ipl->image_addr + 0x10 : +- ipl->image_addr, ++ ipl->is_kdump ? IMAGE_ENTRY_KDUMP : ++ IMAGE_ENTRY, + (info->type == disk_type_scsi) ? 0 : 1, + flags, ipl->image_addr, image_size); + if (rc) { +@@ -1187,7 +1187,7 @@ bootmap_create(struct job_data *job, dis + ulong unused_size; + + /* Use approximated stage 3 size as starting point */ +- size = MINIMUM_ADDRESS; ++ size = IMAGE_LOAD_ADDRESS; + + /* Ramdisk */ + if (job->data.dump.ramdisk != NULL) { +@@ -1199,7 +1199,7 @@ bootmap_create(struct job_data *job, dis + /* Kernel */ + if (stat(job->data.dump.image, &st)) + goto out_misc_free_temp_dev; +- size += DIV_ROUND_UP(st.st_size - 0x10000, ++ size += DIV_ROUND_UP(st.st_size - IMAGE_LOAD_ADDRESS, + info->phy_block_size); + /* Parmfile */ + size += DIV_ROUND_UP(DUMP_PARAM_MAX_LEN, info->phy_block_size); +--- a/zipl/src/job.c ++++ b/zipl/src/job.c +@@ -23,6 +23,7 @@ + #include "job.h" + #include "misc.h" + #include "scan.h" ++#include "zipl.h" + + /* Command line options */ + static struct option options[] = { +@@ -663,12 +664,12 @@ check_component_address_data(struct comp + address_limit); + return -1; + } +- if (*cl[i].addrp < MINIMUM_ADDRESS) { ++ if (*cl[i].addrp < IMAGE_LOAD_ADDRESS) { + if (name != NULL) + error_text("Section '%s'", name); + error_reason("Component '%s' falls below available " + "address space (limit is 0x%08x)", +- cl[i].name, MINIMUM_ADDRESS); ++ cl[i].name, IMAGE_LOAD_ADDRESS); + return -1; + } + } +@@ -706,12 +707,12 @@ finalize_component_address_data(struct c + for (j = -1; j < i; j++) { + if (j < 0) { + /* Try address before first component */ +- addr = MINIMUM_ADDRESS; ++ addr = IMAGE_LOAD_ADDRESS; + } else { + /* Try address after component j */ + addr = *cl[j].addrp + cl[j].size; +- if (addr < MINIMUM_ADDRESS) +- addr = MINIMUM_ADDRESS; ++ if (addr < IMAGE_LOAD_ADDRESS) ++ addr = IMAGE_LOAD_ADDRESS; + } + addr = ALIGN(addr, cl[i].align); + if (addr + cl[i].size > address_limit) { +@@ -905,7 +906,7 @@ check_job_dump_images(struct job_dump_da + dump->image = misc_strdup(ZFCPDUMP_IMAGE); + if (dump->image == NULL) + return -1; +- dump->image_addr = DEFAULT_IMAGE_ADDRESS; ++ dump->image_addr = IMAGE_LOAD_ADDRESS; + + /* Ramdisk is no longer required with new initramfs dump system */ + if (misc_check_readable_file(ZFCPDUMP_INITRD)) +@@ -1351,7 +1352,7 @@ get_job_from_section_data(char* data[], + return -1; + if (extract_address(job->data.ipl.image, + &job->data.ipl.image_addr)) { +- job->data.ipl.image_addr = DEFAULT_IMAGE_ADDRESS; ++ job->data.ipl.image_addr = IMAGE_LOAD_ADDRESS; + } + /* Fill in parmline */ + rc = get_parmline(data[(int) scan_keyword_parmfile], +@@ -1406,7 +1407,7 @@ get_job_from_section_data(char* data[], + return -1; + if (extract_address(job->data.ipl_tape.image, + &job->data.ipl_tape.image_addr)) { +- job->data.ipl_tape.image_addr = DEFAULT_IMAGE_ADDRESS; ++ job->data.ipl_tape.image_addr = IMAGE_LOAD_ADDRESS; + } + /* Fill in parmline */ + rc = get_parmline(data[(int) scan_keyword_parmfile], diff --git a/s390-tools-sles15sp2-15-zipl-Consolidate-STAGE-2-3-macros.patch b/s390-tools-sles15sp2-15-zipl-Consolidate-STAGE-2-3-macros.patch new file mode 100644 index 0000000..2cd33c5 --- /dev/null +++ b/s390-tools-sles15sp2-15-zipl-Consolidate-STAGE-2-3-macros.patch @@ -0,0 +1,110 @@ +Subject: [PATCH] [FEAT VS1804] zipl: Consolidate STAGE{2,3} macros +From: Marc Hartmayer + +Summary: genprotimg: Introduce new tool for the creation of PV images +Description: genprotimg takes a kernel, host-key documents, optionally an + initrd, optionally a file with the kernel command line, and it + generates a single, loadable image file. The image consists of a + concatenation of a plain text boot loader, the encrypted + components for kernel, initrd, and cmdline, and the + integrity-protected PV header, containing metadata necessary for + running the guest in PV mode. It's possible to use this image file + as a kernel for zIPL or for a direct kernel boot using QEMU. +Upstream-ID: 4762e65acbc4efe7142ccb5fd2ef86073737ebd8 +Problem-ID: VS1804 + +Upstream-Description: + + zipl: Consolidate STAGE{2,3} macros + + Increase consistency with the other macros by moving and renaming + the STAGE{2,3} macros in zipl.h. + + Signed-off-by: Philipp Rudo + Reviewed-by: Stefan Haberland + Signed-off-by: Jan Höppner + + +Signed-off-by: Marc Hartmayer +--- + zipl/include/zipl.h | 8 ++++---- + zipl/src/boot.c | 4 ++-- + zipl/src/bootmap.c | 6 +++--- + 3 files changed, 9 insertions(+), 9 deletions(-) + +--- a/zipl/include/zipl.h ++++ b/zipl/include/zipl.h +@@ -19,13 +19,12 @@ + #define ZIPL_MAGIC_SIZE 4 + #define DISK_LAYOUT_ID 0x00000001 + ++#define STAGE3_ENTRY 0xa000UL + #define IMAGE_ENTRY 0x10000UL + #define IMAGE_ENTRY_KDUMP 0x10010UL + +-#define ZIPL_STAGE2_LOAD_ADDRESS 0x2000UL +-#define ZIPL_STAGE3_ENTRY_ADDRESS 0xa000UL +-#define DEFAULT_STAGE3_ADDRESS 0xa000UL +-#define DEFAULT_STAGE3_PARAMS_ADDRESS 0x9000UL ++#define STAGE2_LOAD_ADDRESS 0x2000UL ++#define STAGE3_LOAD_ADDRESS 0xa000UL + #define IMAGE_LOAD_ADDRESS IMAGE_ENTRY + + #define ADDRESS_LIMIT 0x80000000UL +@@ -38,6 +37,7 @@ + #define STAGE3_HEAP_ADDRESS 0x2000UL + #define STAGE3_STACK_SIZE 0x1000UL + #define STAGE3_STACK_ADDRESS 0xF000UL ++#define STAGE3_PARAMS_ADDRESS 0x9000UL + + #define PSW_ADDRESS_MASK 0x000000007fffffffUL + #define PSW_LOAD 0x0008000080000000UL +--- a/zipl/src/boot.c ++++ b/zipl/src/boot.c +@@ -195,7 +195,7 @@ boot_init_fba_stage1b(struct boot_fba_st + stage1b->locdata[i].blocknr = + (uint32_t) stage2_list[i].linear.block; + stage1b->locread[i].read.address_lo = +- ZIPL_STAGE2_LOAD_ADDRESS + i * FBA_BLK_SIZE; ++ STAGE2_LOAD_ADDRESS + i * FBA_BLK_SIZE; + } + /* Terminate CCW chain */ + stage1b->locread[i - 1].read.flags &= ~CCW_FLAG_CC; +@@ -220,7 +220,7 @@ boot_init_eckd_stage1b(struct boot_eckd_ + stage1b->seek[i].head = stage2_list[i].chs.head | + ((stage2_list[i].chs.cyl >> 12) & 0xfff0); + stage1b->seek[i].sec = stage2_list[i].chs.sec; +- stage1b->ssrt[i].read.address_lo = ZIPL_STAGE2_LOAD_ADDRESS + ++ stage1b->ssrt[i].read.address_lo = STAGE2_LOAD_ADDRESS + + i * stage2_list[i].chs.size; + stage1b->ssrt[i].read.flags = CCW_FLAG_CC | CCW_FLAG_SLI; + } +--- a/zipl/src/bootmap.c ++++ b/zipl/src/bootmap.c +@@ -627,7 +627,7 @@ add_ipl_program(int fd, struct job_ipl_d + } + + /* Add stage 3 loader to bootmap */ +- rc = add_component_file(fd, ZIPL_STAGE3_PATH, DEFAULT_STAGE3_ADDRESS, ++ rc = add_component_file(fd, ZIPL_STAGE3_PATH, STAGE3_LOAD_ADDRESS, + signature_size, VOID_ADD(table, offset), 1, + info, target, &comp_loc[comp_nr]); + if (rc) { +@@ -654,7 +654,7 @@ add_ipl_program(int fd, struct job_ipl_d + } + rc = add_component_buffer(fd, stage3_params, stage3_params_size, + (component_data) (uint64_t) +- DEFAULT_STAGE3_PARAMS_ADDRESS, ++ STAGE3_PARAMS_ADDRESS, + VOID_ADD(table, offset), info, + &comp_loc[comp_nr], component_load); + free(stage3_params); +@@ -792,7 +792,7 @@ add_ipl_program(int fd, struct job_ipl_d + create_component_entry(VOID_ADD(table, offset), NULL, + component_execute, + (component_data) (uint64_t) +- (ZIPL_STAGE3_ENTRY_ADDRESS | PSW_LOAD), ++ (STAGE3_ENTRY | PSW_LOAD), + info); + /* Write component table */ + rc = disk_write_block_aligned(fd, table, info->phy_block_size, diff --git a/s390-tools-sles15sp2-16-zipl-stfle-use-uint64_t-instead-of-u64.patch b/s390-tools-sles15sp2-16-zipl-stfle-use-uint64_t-instead-of-u64.patch new file mode 100644 index 0000000..b42835f --- /dev/null +++ b/s390-tools-sles15sp2-16-zipl-stfle-use-uint64_t-instead-of-u64.patch @@ -0,0 +1,53 @@ +Subject: [PATCH] [FEAT VS1804] zipl: stfle: use uint64_t instead of u64 +From: Marc Hartmayer + +Summary: genprotimg: Introduce new tool for the creation of PV images +Description: genprotimg takes a kernel, host-key documents, optionally an + initrd, optionally a file with the kernel command line, and it + generates a single, loadable image file. The image consists of a + concatenation of a plain text boot loader, the encrypted + components for kernel, initrd, and cmdline, and the + integrity-protected PV header, containing metadata necessary for + running the guest in PV mode. It's possible to use this image file + as a kernel for zIPL or for a direct kernel boot using QEMU. +Upstream-ID: 9d1baaa594d796ca9fe6bdf1282c78e4b2ff5234 +Problem-ID: VS1804 + +Upstream-Description: + + zipl: stfle: use uint64_t instead of u64 + + As the definition of `stfle_fac_list` in the lowcore uses uint64_t, we + should also use uint64_t for the `stfle_fac_list` parameter of the + `stfle/__stfle_asm` function. + + Signed-off-by: Marc Hartmayer + Reviewed-by: Stefan Haberland + + +Signed-off-by: Marc Hartmayer +--- + zipl/boot/s390.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/zipl/boot/s390.h ++++ b/zipl/boot/s390.h +@@ -452,7 +452,7 @@ static inline int test_facility(unsigned + return __test_facility(nr, &S390_lowcore.stfle_fac_list); + } + +-static inline unsigned long __stfle_asm(u64 *stfle_fac_list, int size) ++static inline unsigned long __stfle_asm(uint64_t *stfle_fac_list, int size) + { + register unsigned long reg0 asm("0") = size - 1; + +@@ -469,7 +469,7 @@ static inline unsigned long __stfle_asm( + * @stfle_fac_list: array where facility list can be stored + * @size: size of passed in array in double words + */ +-static inline void stfle(u64 *stfle_fac_list, int size) ++static inline void stfle(uint64_t *stfle_fac_list, int size) + { + unsigned long nr; + diff --git a/s390-tools-sles15sp2-17-zipl-boot-fix-comment-in-stage3.lds.patch b/s390-tools-sles15sp2-17-zipl-boot-fix-comment-in-stage3.lds.patch new file mode 100644 index 0000000..52072cc --- /dev/null +++ b/s390-tools-sles15sp2-17-zipl-boot-fix-comment-in-stage3.lds.patch @@ -0,0 +1,42 @@ +Subject: [PATCH] [FEAT VS1804] zipl/boot: fix comment in stage3.lds +From: Marc Hartmayer + +Summary: genprotimg: Introduce new tool for the creation of PV images +Description: genprotimg takes a kernel, host-key documents, optionally an + initrd, optionally a file with the kernel command line, and it + generates a single, loadable image file. The image consists of a + concatenation of a plain text boot loader, the encrypted + components for kernel, initrd, and cmdline, and the + integrity-protected PV header, containing metadata necessary for + running the guest in PV mode. It's possible to use this image file + as a kernel for zIPL or for a direct kernel boot using QEMU. +Upstream-ID: 971970989bbb1de8887d11b0ab8e4f19adbd484f +Problem-ID: VS1804 + +Upstream-Description: + + zipl/boot: fix comment in stage3.lds + + See STAGE3_STACK_ADDRESS macro. + + Reviewed-by: Jan Höppner + Signed-off-by: Marc Hartmayer + Signed-off-by: Jan Höppner + + +Signed-off-by: Marc Hartmayer +--- + zipl/boot/stage3.lds | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/zipl/boot/stage3.lds ++++ b/zipl/boot/stage3.lds +@@ -10,7 +10,7 @@ + * 0x6000-0x8fff free + * 0x9000-0x9fff Stage3 parameter + * 0xa000-0xdfff Stage3 code + data +- * 0xe000-0xffff Stack ++ * 0xf000-0xffff Stack + */ + + SECTIONS diff --git a/s390-tools-sles15sp2-18-lib-zt_common-add-STATIC_ASSERT-macro.patch b/s390-tools-sles15sp2-18-lib-zt_common-add-STATIC_ASSERT-macro.patch new file mode 100644 index 0000000..ee4a6ab --- /dev/null +++ b/s390-tools-sles15sp2-18-lib-zt_common-add-STATIC_ASSERT-macro.patch @@ -0,0 +1,50 @@ +Subject: [PATCH] [FEAT VS1804] lib/zt_common: add STATIC_ASSERT macro +From: Marc Hartmayer + +Summary: genprotimg: Introduce new tool for the creation of PV images +Description: genprotimg takes a kernel, host-key documents, optionally an + initrd, optionally a file with the kernel command line, and it + generates a single, loadable image file. The image consists of a + concatenation of a plain text boot loader, the encrypted + components for kernel, initrd, and cmdline, and the + integrity-protected PV header, containing metadata necessary for + running the guest in PV mode. It's possible to use this image file + as a kernel for zIPL or for a direct kernel boot using QEMU. +Upstream-ID: bac3f93772bdf8618c2c9677c59569d70e4a39c0 +Problem-ID: VS1804 + +Upstream-Description: + + lib/zt_common: add STATIC_ASSERT macro + + Add `STATIC_ASSERT` macro that uses `_Static_assert` if available (was + introduced with gcc 4.6, see https://gcc.gnu.org/wiki/C11Status). For + example, this could be used for the verification of structure sizes at + compile time. + + Acked-by: Jan Höppner + Signed-off-by: Marc Hartmayer + Signed-off-by: Jan Höppner + + +Signed-off-by: Marc Hartmayer +--- + include/lib/zt_common.h | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/include/lib/zt_common.h ++++ b/include/lib/zt_common.h +@@ -22,6 +22,13 @@ + # define UNUSED(x) x + #endif + ++#ifdef STATIC_ASSERT ++#elif defined(__GNUC__) && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __GNUC__ >= 5) ++# define STATIC_ASSERT(test) _Static_assert((test), "(" #test ") failed"); ++#else ++# define STATIC_ASSERT(test) ++#endif ++ + #define RELEASE_STRING STRINGIFY (S390_TOOLS_RELEASE) + #define TOOLS_LIBDIR STRINGIFY (S390_TOOLS_LIBDIR) + #define TOOLS_SYSCONFDIR STRINGIFY (S390_TOOLS_SYSCONFDIR) diff --git a/s390-tools-sles15sp2-19-zipl-use-STATIC_ASSERT-macro-for-no-padding-verifica.patch b/s390-tools-sles15sp2-19-zipl-use-STATIC_ASSERT-macro-for-no-padding-verifica.patch new file mode 100644 index 0000000..2a3072b --- /dev/null +++ b/s390-tools-sles15sp2-19-zipl-use-STATIC_ASSERT-macro-for-no-padding-verifica.patch @@ -0,0 +1,91 @@ +Subject: [PATCH] [FEAT VS1804] zipl: use STATIC_ASSERT macro for no padding verification +From: Marc Hartmayer + +Summary: genprotimg: Introduce new tool for the creation of PV images +Description: genprotimg takes a kernel, host-key documents, optionally an + initrd, optionally a file with the kernel command line, and it + generates a single, loadable image file. The image consists of a + concatenation of a plain text boot loader, the encrypted + components for kernel, initrd, and cmdline, and the + integrity-protected PV header, containing metadata necessary for + running the guest in PV mode. It's possible to use this image file + as a kernel for zIPL or for a direct kernel boot using QEMU. +Upstream-ID: cc16e41595d6dcb942f84443f27a1b52d06d17da +Problem-ID: VS1804 + +Upstream-Description: + + zipl: use STATIC_ASSERT macro for no padding verification + + A simple comment above the struct declaration to indicate that the + structure must not have any padding is prone to error. Therefore let's + add a check for the structure size at compile time. + + Reviewed-by: Jan Höppner + Signed-off-by: Marc Hartmayer + Signed-off-by: Jan Höppner + + +Signed-off-by: Marc Hartmayer +--- + zipl/boot/sclp.h | 2 ++ + zipl/boot/sclp_stage3.h | 2 ++ + zipl/boot/stage3.h | 4 ++++ + 3 files changed, 8 insertions(+) + +--- a/zipl/boot/sclp.h ++++ b/zipl/boot/sclp.h +@@ -60,6 +60,7 @@ struct sccb_header { + uint8_t control_mask[3]; + uint16_t response_code; + }; ++STATIC_ASSERT(sizeof(struct sccb_header) == 2 + 1 + 3 + 2) + + /* Structure must not have any padding */ + struct evbuf_header { +@@ -68,6 +69,7 @@ struct evbuf_header { + uint8_t flags; + uint16_t _reserved; + }; ++STATIC_ASSERT(sizeof(struct evbuf_header) == 2 + 1 + 1 + 2) + + struct mto { + uint16_t length; +--- a/zipl/boot/sclp_stage3.h ++++ b/zipl/boot/sclp_stage3.h +@@ -42,6 +42,8 @@ struct sdias_sccb { + struct sccb_header header; + struct sdias_evbuf evbuf; + }; ++STATIC_ASSERT(sizeof(struct sdias_sccb) == ++ sizeof(struct sccb_header) + sizeof(struct sdias_evbuf)) + + + int sclp_hsa_copy(void *, unsigned long, unsigned long); +--- a/zipl/boot/stage3.h ++++ b/zipl/boot/stage3.h +@@ -15,6 +15,8 @@ + #include "libc.h" + #include "s390.h" + ++#include "lib/zt_common.h" ++ + #define IPL_DEVICE 0x10404UL + #define INITRD_START 0x10408UL + #define INITRD_SIZE 0x10410UL +@@ -128,6 +130,7 @@ struct ipl_rb_hdr { + uint8_t rbt; + uint8_t reserved1[11]; + }; ++STATIC_ASSERT(sizeof(struct ipl_rb_hdr) == 4 + 1 + 11) + + /* IPL Report Block types */ + enum ipl_rbt { +@@ -168,6 +171,7 @@ struct ipl_rb_components { + uint8_t reserved1[11]; + struct ipl_rb_component_entry entries[]; + }; ++STATIC_ASSERT(sizeof(struct ipl_rb_components) == 4 + 1 + 11) + + extern unsigned long long _parm_addr; /* address of parmline */ + extern unsigned long long _initrd_addr; /* address of initrd */ diff --git a/s390-tools-sles15sp2-20-Support-lib-zt_common.h-to-be-used-in-assembler-and-.patch b/s390-tools-sles15sp2-20-Support-lib-zt_common.h-to-be-used-in-assembler-and-.patch new file mode 100644 index 0000000..e354900 --- /dev/null +++ b/s390-tools-sles15sp2-20-Support-lib-zt_common.h-to-be-used-in-assembler-and-.patch @@ -0,0 +1,65 @@ +Subject: [PATCH] [FEAT VS1804] Support `lib/zt_common.h` to be used in assembler and add `_AC` macro +From: Marc Hartmayer + +Summary: genprotimg: Introduce new tool for the creation of PV images +Description: genprotimg takes a kernel, host-key documents, optionally an + initrd, optionally a file with the kernel command line, and it + generates a single, loadable image file. The image consists of a + concatenation of a plain text boot loader, the encrypted + components for kernel, initrd, and cmdline, and the + integrity-protected PV header, containing metadata necessary for + running the guest in PV mode. It's possible to use this image file + as a kernel for zIPL or for a direct kernel boot using QEMU. +Upstream-ID: 400167f5128a14ba48b0d05b7b777b42c450c73f +Problem-ID: VS1804 + +Upstream-Description: + + Support `lib/zt_common.h` to be used in assembler and add `_AC` macro + + Support `lib/zt_common.h` to be used in assembler files. In addition, + add the macro `_AC` that can be used to make constant macros usable in + both assembler and C code. + + Suggested-by: Philipp Rudo + Reviewed-by: Stefan Haberland + Reviewed-by: Philipp Rudo + Signed-off-by: Marc Hartmayer + Signed-off-by: Jan Höppner + + +Signed-off-by: Marc Hartmayer +--- + include/lib/zt_common.h | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +--- a/include/lib/zt_common.h ++++ b/include/lib/zt_common.h +@@ -15,6 +15,21 @@ + #define STRINGIFY_1(x) #x + #define STRINGIFY(x) STRINGIFY_1(x) + ++/* Use this macro to make constant macros usable in both assembler and ++ * C code. ++ * ++ * Usage example: ++ * #define IMAGE_ENTRY _AC(0x10000, UL) ++ */ ++#ifdef __ASSEMBLER__ ++#define _AC(X, TYPE) X ++#else ++#define _AC(X, TYPE) X##TYPE ++#endif ++ ++ ++#ifndef __ASSEMBLER__ ++ + #ifdef UNUSED + #elif defined(__GNUC__) + # define UNUSED(x) UNUSED_ ## x __attribute__((unused)) +@@ -50,4 +65,5 @@ typedef signed short int s16; + typedef unsigned char u8; + typedef signed char s8; + ++#endif /* __ASSEMBLER__ */ + #endif /* LIB_ZT_COMMON_H */ diff --git a/s390-tools-sles15sp2-21-zipl-move-IPL-related-definitions-into-separate-head.patch b/s390-tools-sles15sp2-21-zipl-move-IPL-related-definitions-into-separate-head.patch new file mode 100644 index 0000000..8762137 --- /dev/null +++ b/s390-tools-sles15sp2-21-zipl-move-IPL-related-definitions-into-separate-head.patch @@ -0,0 +1,359 @@ +Subject: [PATCH] [FEAT VS1804] zipl: move IPL related definitions into separate header +From: Marc Hartmayer + +Summary: genprotimg: Introduce new tool for the creation of PV images +Description: genprotimg takes a kernel, host-key documents, optionally an + initrd, optionally a file with the kernel command line, and it + generates a single, loadable image file. The image consists of a + concatenation of a plain text boot loader, the encrypted + components for kernel, initrd, and cmdline, and the + integrity-protected PV header, containing metadata necessary for + running the guest in PV mode. It's possible to use this image file + as a kernel for zIPL or for a direct kernel boot using QEMU. +Upstream-ID: 9d39a4bd47008b15bbf4ebe672b91d6d63888536 +Problem-ID: VS1804 + +Upstream-Description: + + zipl: move IPL related definitions into separate header + + Move the IPL related definitions into `include/boot/ipl.h`. This + allows the reuse of the definitions, e.g. in the boot loader for + protected guests. + + Reviewed-by: Stefan Haberland + Reviewed-by: Philipp Rudo + Signed-off-by: Marc Hartmayer + Signed-off-by: Jan Höppner + + +Signed-off-by: Marc Hartmayer +--- + include/boot/ipl.h | 159 +++++++++++++++++++++++++++++++++++++++++++++++++++++ + zipl/boot/stage3.h | 140 ---------------------------------------------- + 2 files changed, 160 insertions(+), 139 deletions(-) + +--- /dev/null ++++ b/include/boot/ipl.h +@@ -0,0 +1,159 @@ ++/* ++ * IPL related definitions ++ * ++ * Copyright IBM Corp. 2020 ++ * ++ * s390-tools is free software; you can redistribute it and/or modify ++ * it under the terms of the MIT license. See LICENSE for details. ++ */ ++ ++#ifndef IPL_H ++#define IPL_H ++ ++#include "lib/zt_common.h" ++ ++#define IPL_FLAG_SECURE 0x40 ++ ++#define IPL_RB_COMPONENT_FLAG_SIGNED 0x80 ++#define IPL_RB_COMPONENT_FLAG_VERIFIED 0x40 ++ ++ ++#ifndef __ASSEMBLER__ ++ ++#include ++ ++/* IPL Parameter List header */ ++struct ipl_pl_hdr { ++ uint32_t len; ++ uint8_t flags; ++ uint8_t reserved1[2]; ++ uint8_t version; ++} __packed; ++ ++/* IPL Parameter Block header */ ++struct ipl_pb_hdr { ++ uint32_t len; ++ uint8_t pbt; ++} __packed; ++ ++/* IPL Parameter Block 0 with common fields */ ++struct ipl_pb0_common { ++ uint32_t len; ++ uint8_t pbt; ++ uint8_t flags; ++ uint8_t reserved1[2]; ++ uint8_t loadparm[8]; ++ uint8_t reserved2[84]; ++} __packed; ++ ++/* IPL Parameter Block 0 for FCP */ ++struct ipl_pb0_fcp { ++ uint32_t len; ++ uint8_t pbt; ++ uint8_t reserved1[3]; ++ uint8_t loadparm[8]; ++ uint8_t reserved2[304]; ++ uint8_t opt; ++ uint8_t reserved3[3]; ++ uint8_t cssid; ++ uint8_t reserved4[1]; ++ uint8_t devno; ++ uint8_t reserved5[4]; ++ uint64_t wwpn; ++ uint64_t lun; ++ uint32_t bootprog; ++ uint8_t reserved6[12]; ++ uint64_t br_lba; ++ uint32_t scp_data_len; ++ uint8_t reserved7[260]; ++ uint8_t scp_data[]; ++} __packed; ++ ++/* IPL Parameter Block 0 for CCW */ ++struct ipl_pb0_ccw { ++ uint32_t len; ++ uint8_t pbt; ++ uint8_t flags; ++ uint8_t reserved1[2]; ++ uint8_t loadparm[8]; ++ uint8_t reserved2[84]; ++ uint16_t reserved3 : 13; ++ uint8_t ssid : 3; ++ uint16_t devno; ++ uint8_t vm_flags; ++ uint8_t reserved4[3]; ++ uint32_t vm_parm_len; ++ uint8_t nss_name[8]; ++ uint8_t vm_parm[64]; ++ uint8_t reserved5[8]; ++} __packed; ++ ++struct ipl_parameter_block { ++ struct ipl_pl_hdr hdr; ++ union { ++ struct ipl_pb_hdr pb0_hdr; ++ struct ipl_pb0_common common; ++ struct ipl_pb0_fcp fcp; ++ struct ipl_pb0_ccw ccw; ++ char raw[PAGE_SIZE - sizeof(struct ipl_pl_hdr)]; ++ }; ++} __packed __aligned(PAGE_SIZE); ++ ++/* IPL Report List header */ ++struct ipl_rl_hdr { ++ uint32_t len; ++ uint8_t flags; ++ uint8_t reserved1[2]; ++ uint8_t version; ++ uint8_t reserved2[8]; ++} __packed; ++ ++/* IPL Report Block header */ ++/* Structure must not have any padding */ ++struct ipl_rb_hdr { ++ uint32_t len; ++ uint8_t rbt; ++ uint8_t reserved1[11]; ++}; ++STATIC_ASSERT(sizeof(struct ipl_rb_hdr) == 4 + 1 + 11) ++ ++/* IPL Report Block types */ ++enum ipl_rbt { ++ IPL_RBT_CERTIFICATES = 1, ++ IPL_RBT_COMPONENTS = 2, ++}; ++ ++/* IPL Report Block for the certificate list */ ++struct ipl_rb_certificate_entry { ++ uint64_t addr; ++ uint64_t len; ++} __packed; ++ ++struct ipl_rb_certificates { ++ uint32_t len; ++ uint8_t rbt; ++ uint8_t reserved1[11]; ++ struct ipl_rb_certificate_entry entries[]; ++} __packed; ++ ++/* IPL Report Block for the component list */ ++struct ipl_rb_component_entry { ++ uint64_t addr; ++ uint64_t len; ++ uint8_t flags; ++ uint8_t reserved1[5]; ++ uint16_t certificate_index; ++ uint8_t reserved2[8]; ++}; ++ ++/* Structure must not have any padding */ ++struct ipl_rb_components { ++ uint32_t len; ++ uint8_t rbt; ++ uint8_t reserved1[11]; ++ struct ipl_rb_component_entry entries[]; ++}; ++STATIC_ASSERT(sizeof(struct ipl_rb_components) == 4 + 1 + 11) ++ ++#endif /* __ASSEMBLER__ */ ++#endif /* IPL_H */ +--- a/zipl/boot/stage3.h ++++ b/zipl/boot/stage3.h +@@ -15,7 +15,7 @@ + #include "libc.h" + #include "s390.h" + +-#include "lib/zt_common.h" ++#include "boot/ipl.h" + + #define IPL_DEVICE 0x10404UL + #define INITRD_START 0x10408UL +@@ -29,150 +29,12 @@ + #define STAGE3_FLAG_SCSI 0x0001000000000000ULL + #define STAGE3_FLAG_KDUMP 0x0002000000000000ULL + +-#define IPL_FLAG_SECURE 0x40 +- + #define DEFAULT_PSW_LOAD 0x0008000080010000UL + #define PSW_ADDR_MASK 0x000000007FFFFFFFUL + + #define UNSPECIFIED_ADDRESS -1UL + + +-/* IPL Parameter List header */ +-struct ipl_pl_hdr { +- uint32_t len; +- uint8_t flags; +- uint8_t reserved1[2]; +- uint8_t version; +-} __packed; +- +-/* IPL Parameter Block header */ +-struct ipl_pb_hdr { +- uint32_t len; +- uint8_t pbt; +-} __packed; +- +-/* IPL Parameter Block 0 with common fields */ +-struct ipl_pb0_common { +- uint32_t len; +- uint8_t pbt; +- uint8_t flags; +- uint8_t reserved1[2]; +- uint8_t loadparm[8]; +- uint8_t reserved2[84]; +-} __packed; +- +-/* IPL Parameter Block 0 for FCP */ +-struct ipl_pb0_fcp { +- uint32_t len; +- uint8_t pbt; +- uint8_t reserved1[3]; +- uint8_t loadparm[8]; +- uint8_t reserved2[304]; +- uint8_t opt; +- uint8_t reserved3[3]; +- uint8_t cssid; +- uint8_t reserved4[1]; +- uint8_t devno; +- uint8_t reserved5[4]; +- uint64_t wwpn; +- uint64_t lun; +- uint32_t bootprog; +- uint8_t reserved6[12]; +- uint64_t br_lba; +- uint32_t scp_data_len; +- uint8_t reserved7[260]; +- uint8_t scp_data[]; +-} __packed; +- +-/* IPL Parameter Block 0 for CCW */ +-struct ipl_pb0_ccw { +- uint32_t len; +- uint8_t pbt; +- uint8_t flags; +- uint8_t reserved1[2]; +- uint8_t loadparm[8]; +- uint8_t reserved2[84]; +- uint16_t reserved3 : 13; +- uint8_t ssid : 3; +- uint16_t devno; +- uint8_t vm_flags; +- uint8_t reserved4[3]; +- uint32_t vm_parm_len; +- uint8_t nss_name[8]; +- uint8_t vm_parm[64]; +- uint8_t reserved5[8]; +-} __packed; +- +-struct ipl_parameter_block { +- struct ipl_pl_hdr hdr; +- union { +- struct ipl_pb_hdr pb0_hdr; +- struct ipl_pb0_common common; +- struct ipl_pb0_fcp fcp; +- struct ipl_pb0_ccw ccw; +- char raw[PAGE_SIZE - sizeof(struct ipl_pl_hdr)]; +- }; +-} __packed __aligned(PAGE_SIZE); +- +-/* IPL Report List header */ +-struct ipl_rl_hdr { +- uint32_t len; +- uint8_t flags; +- uint8_t reserved1[2]; +- uint8_t version; +- uint8_t reserved2[8]; +-} __packed; +- +-/* IPL Report Block header */ +-/* Structure must not have any padding */ +-struct ipl_rb_hdr { +- uint32_t len; +- uint8_t rbt; +- uint8_t reserved1[11]; +-}; +-STATIC_ASSERT(sizeof(struct ipl_rb_hdr) == 4 + 1 + 11) +- +-/* IPL Report Block types */ +-enum ipl_rbt { +- IPL_RBT_CERTIFICATES = 1, +- IPL_RBT_COMPONENTS = 2, +-}; +- +-/* IPL Report Block for the certificate list */ +-struct ipl_rb_certificate_entry { +- uint64_t addr; +- uint64_t len; +-} __packed; +- +-struct ipl_rb_certificates { +- uint32_t len; +- uint8_t rbt; +- uint8_t reserved1[11]; +- struct ipl_rb_certificate_entry entries[]; +-} __packed; +- +-/* IPL Report Block for the component list */ +-struct ipl_rb_component_entry { +- uint64_t addr; +- uint64_t len; +- uint8_t flags; +- uint8_t reserved1[5]; +- uint16_t certificate_index; +- uint8_t reserved2[8]; +-}; +- +-#define IPL_RB_COMPONENT_FLAG_SIGNED 0x80 +-#define IPL_RB_COMPONENT_FLAG_VERIFIED 0x40 +- +-/* Structure must not have any padding */ +-struct ipl_rb_components { +- uint32_t len; +- uint8_t rbt; +- uint8_t reserved1[11]; +- struct ipl_rb_component_entry entries[]; +-}; +-STATIC_ASSERT(sizeof(struct ipl_rb_components) == 4 + 1 + 11) +- + extern unsigned long long _parm_addr; /* address of parmline */ + extern unsigned long long _initrd_addr; /* address of initrd */ + extern unsigned long long _initrd_len; /* length of initrd */ diff --git a/s390-tools-sles15sp2-22-zipl-move-SIGP-related-functions-and-definitions-int.patch b/s390-tools-sles15sp2-22-zipl-move-SIGP-related-functions-and-definitions-int.patch new file mode 100644 index 0000000..a86d1c5 --- /dev/null +++ b/s390-tools-sles15sp2-22-zipl-move-SIGP-related-functions-and-definitions-int.patch @@ -0,0 +1,148 @@ +Subject: [PATCH] [FEAT VS1804] zipl: move SIGP related functions and definitions into separate header +From: Marc Hartmayer + +Summary: genprotimg: Introduce new tool for the creation of PV images +Description: genprotimg takes a kernel, host-key documents, optionally an + initrd, optionally a file with the kernel command line, and it + generates a single, loadable image file. The image consists of a + concatenation of a plain text boot loader, the encrypted + components for kernel, initrd, and cmdline, and the + integrity-protected PV header, containing metadata necessary for + running the guest in PV mode. It's possible to use this image file + as a kernel for zIPL or for a direct kernel boot using QEMU. +Upstream-ID: 675c854fa3239882c59a9419c776eb13bc70cf76 +Problem-ID: VS1804 + +Upstream-Description: + + zipl: move SIGP related functions and definitions into separate header + + Move SIGP related functions and definitions to + `include/boot/sigp.h`. This allows the reuse of the definitions in + assembler files. + + Reviewed-by: Stefan Haberland + Acked-by: Janosch Frank + Reviewed-by: Philipp Rudo + Signed-off-by: Marc Hartmayer + Signed-off-by: Jan Höppner + + +Signed-off-by: Marc Hartmayer +--- + include/boot/sigp.h | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++ + zipl/boot/s390.h | 38 ----------------------------------- + 2 files changed, 56 insertions(+), 37 deletions(-) + +--- /dev/null ++++ b/include/boot/sigp.h +@@ -0,0 +1,55 @@ ++/* ++ * SIGP related definitions and functions. ++ * ++ * Copyright IBM Corp. 2020 ++ * ++ * s390-tools is free software; you can redistribute it and/or modify ++ * it under the terms of the MIT license. See LICENSE for details. ++ */ ++ ++#ifndef S390_SIGP_H ++#define S390_SIGP_H ++ ++/* Signal Processor Order Codes */ ++#define SIGP_STOP_AND_STORE_STATUS 9 ++#define SIGP_SET_MULTI_THREADING 22 ++#define SIGP_STORE_ASTATUS_AT_ADDRESS 23 ++ ++/* Signal Processor Condition Codes */ ++#define SIGP_CC_ORDER_CODE_ACCEPTED 0 ++#define SIGP_CC_BUSY 2 ++ ++ ++#ifndef __ASSEMBLER__ ++ ++#include ++ ++static inline int sigp(uint16_t addr, uint8_t order, uint32_t parm, ++ uint32_t *status) ++{ ++ register unsigned int reg1 asm ("1") = parm; ++ int cc; ++ ++ asm volatile( ++ " sigp %1,%2,0(%3)\n" ++ " ipm %0\n" ++ " srl %0,28\n" ++ : "=d" (cc), "+d" (reg1) : "d" (addr), "a" (order) : "cc"); ++ if (status && cc == 1) ++ *status = reg1; ++ return cc; ++} ++ ++static inline int sigp_busy(uint16_t addr, uint8_t order, uint32_t parm, ++ uint32_t *status) ++{ ++ int cc; ++ ++ do { ++ cc = sigp(addr, order, parm, status); ++ } while (cc == SIGP_CC_BUSY); ++ return cc; ++} ++ ++#endif /* __ASSEMBLER__ */ ++#endif /* S390_SIGP_H */ +--- a/zipl/boot/s390.h ++++ b/zipl/boot/s390.h +@@ -13,6 +13,7 @@ + + #include "lib/zt_common.h" + #include "libc.h" ++#include "boot/sigp.h" + + #define __pa32(x) ((uint32_t)(unsigned long)(x)) + #define __pa(x) ((unsigned long)(x)) +@@ -295,43 +296,6 @@ static inline int diag308(unsigned long + } + + /* +- * Signal Processor +- */ +-#define SIGP_STOP_AND_STORE_STATUS 9 +-#define SIGP_SET_MULTI_THREADING 22 +-#define SIGP_STORE_ASTATUS_AT_ADDRESS 23 +- +-#define SIGP_CC_ORDER_CODE_ACCEPTED 0 +-#define SIGP_CC_BUSY 2 +- +-static inline int sigp(uint16_t addr, uint8_t order, uint32_t parm, +- uint32_t *status) +-{ +- register unsigned int reg1 asm ("1") = parm; +- int cc; +- +- asm volatile( +- " sigp %1,%2,0(%3)\n" +- " ipm %0\n" +- " srl %0,28\n" +- : "=d" (cc), "+d" (reg1) : "d" (addr), "a" (order) : "cc"); +- if (status && cc == 1) +- *status = reg1; +- return cc; +-} +- +-static inline int sigp_busy(uint16_t addr, uint8_t order, uint32_t parm, +- uint32_t *status) +-{ +- int cc; +- +- do { +- cc = sigp(addr, order, parm, status); +- } while (cc == SIGP_CC_BUSY); +- return cc; +-} +- +-/* + * Store CPU address + */ + static inline unsigned short stap(void) diff --git a/s390-tools-sles15sp2-23-zipl-add-SIGP_SET_ARCHITECTURE-to-sigp.h-and-use-it.patch b/s390-tools-sles15sp2-23-zipl-add-SIGP_SET_ARCHITECTURE-to-sigp.h-and-use-it.patch new file mode 100644 index 0000000..bba542b --- /dev/null +++ b/s390-tools-sles15sp2-23-zipl-add-SIGP_SET_ARCHITECTURE-to-sigp.h-and-use-it.patch @@ -0,0 +1,117 @@ +Subject: [PATCH] [FEAT VS1804] zipl: add SIGP_SET_ARCHITECTURE to sigp.h and use it +From: Marc Hartmayer + +Summary: genprotimg: Introduce new tool for the creation of PV images +Description: genprotimg takes a kernel, host-key documents, optionally an + initrd, optionally a file with the kernel command line, and it + generates a single, loadable image file. The image consists of a + concatenation of a plain text boot loader, the encrypted + components for kernel, initrd, and cmdline, and the + integrity-protected PV header, containing metadata necessary for + running the guest in PV mode. It's possible to use this image file + as a kernel for zIPL or for a direct kernel boot using QEMU. +Upstream-ID: 0e385a81caf7c266c0784613e0264c03271eb99a +Problem-ID: VS1804 + +Upstream-Description: + + zipl: add SIGP_SET_ARCHITECTURE to sigp.h and use it + + This makes the code easier to read. + + Reviewed-by: Philipp Rudo + Reviewed-by: Stefan Haberland + Signed-off-by: Marc Hartmayer + Signed-off-by: Jan Höppner + + +Signed-off-by: Marc Hartmayer +--- + include/boot/sigp.h | 1 + + zipl/boot/head.S | 6 ++++-- + zipl/boot/stage3.c | 6 ++++-- + zipl/boot/tape0.S | 6 ++++-- + 4 files changed, 13 insertions(+), 6 deletions(-) + +--- a/include/boot/sigp.h ++++ b/include/boot/sigp.h +@@ -12,6 +12,7 @@ + + /* Signal Processor Order Codes */ + #define SIGP_STOP_AND_STORE_STATUS 9 ++#define SIGP_SET_ARCHITECTURE 18 + #define SIGP_SET_MULTI_THREADING 22 + #define SIGP_STORE_ASTATUS_AT_ADDRESS 23 + +--- a/zipl/boot/head.S ++++ b/zipl/boot/head.S +@@ -9,16 +9,18 @@ + * it under the terms of the MIT license. See LICENSE for details. + */ + ++#include "boot/sigp.h" ++ + .section .text.start + .globl _start + _start: + basr %r13,0 + 0: la %r7,2 /* First try code 2: */ + la %r6,0 /* 64 bit psws are restored */ +- sigp %r7,%r6,0x12 /* Switch to 64 bit */ ++ sigp %r7,%r6,SIGP_SET_ARCHITECTURE /* Switch to 64 bit */ + bc 8,.Lswitched_64-0b(%r13) /* Accepted ? */ + la %r7,1 /* Failed - try code 1 */ +- sigp %r7,%r6,0x12 /* Switch to 64 bit */ ++ sigp %r7,%r6,SIGP_SET_ARCHITECTURE /* Switch to 64 bit */ + .Lswitched_64: + sam64 /* Switch to 64 bit addr mode */ + basr %r13,0 +--- a/zipl/boot/stage3.c ++++ b/zipl/boot/stage3.c +@@ -10,6 +10,7 @@ + */ + + #include "libc.h" ++#include "boot/sigp.h" + #include "s390.h" + #include "stage3.h" + #include "error.h" +@@ -194,11 +195,12 @@ static inline void __noreturn start_kern + " sam31\n" + " sr %r1,%r1\n" + " sr %r2,%r2\n" +- " sigp %r1,%r2,0x12\n" ++ " sigp %r1,%r2,%[order]\n" + " lpsw 0\n" + : [addr] "=&d" (addr), + [code] "+&d" (code) +- : [psw] "a" (psw) ); ++ : [psw] "a" (psw), ++ [order] "L" (SIGP_SET_ARCHITECTURE)); + while (1); + } + +--- a/zipl/boot/tape0.S ++++ b/zipl/boot/tape0.S +@@ -7,6 +7,8 @@ + # it under the terms of the MIT license. See LICENSE for details. + # + ++#include "boot/sigp.h" ++ + IPL_BS = 1024 # block size for tape access + IPL_OFF = 0x4000 # temporary kernel load addr + COMMAND_LINE_SIZE = 896 # max command line length +@@ -184,10 +186,10 @@ iplstart: + 0: + la %r7,2 #/* First try code 2: */ + la %r6,0 #/* 64 bit psws are restored */ +- sigp %r7,%r6,0x12 #/* Switch to 64 bit */ ++ sigp %r7,%r6,SIGP_SET_ARCHITECTURE #/* Switch to 64 bit */ + bc 8,.Lswitched_64-0b(%r13) #/* Accepted ? */ + la %r7,1 #/* Failed - try code 1 */ +- sigp %r7,%r6,0x12 #/* Switch to 64 bit */ ++ sigp %r7,%r6,SIGP_SET_ARCHITECTURE #/* Switch to 64 bit */ + .Lswitched_64: + sam64 #/* Switch to 64 bit addr mode */ + basr %r13,0 diff --git a/s390-tools-sles15sp2-24-zipl-stage3-make-IPL_DEVICE-definition-consistent-wi.patch b/s390-tools-sles15sp2-24-zipl-stage3-make-IPL_DEVICE-definition-consistent-wi.patch new file mode 100644 index 0000000..46043aa --- /dev/null +++ b/s390-tools-sles15sp2-24-zipl-stage3-make-IPL_DEVICE-definition-consistent-wi.patch @@ -0,0 +1,56 @@ +Subject: [PATCH] [FEAT VS1804] zipl/stage3: make IPL_DEVICE definition consistent with tape0.S +From: Marc Hartmayer + +Summary: genprotimg: Introduce new tool for the creation of PV images +Description: genprotimg takes a kernel, host-key documents, optionally an + initrd, optionally a file with the kernel command line, and it + generates a single, loadable image file. The image consists of a + concatenation of a plain text boot loader, the encrypted + components for kernel, initrd, and cmdline, and the + integrity-protected PV header, containing metadata necessary for + running the guest in PV mode. It's possible to use this image file + as a kernel for zIPL or for a direct kernel boot using QEMU. +Upstream-ID: d884fb8db4c4f383780d6fc8087abd8f80e1c8b8 +Problem-ID: VS1804 + +Upstream-Description: + + zipl/stage3: make IPL_DEVICE definition consistent with tape0.S + + Make `IPL_DEVICE` definition consistent with the kernel definition and + the definition in tape0.S. This allows us to refactor the code later. + + Reviewed-by: Philipp Rudo + Reviewed-by: Stefan Haberland + Signed-off-by: Marc Hartmayer + Signed-off-by: Jan Höppner + + +Signed-off-by: Marc Hartmayer +--- + zipl/boot/stage3.c | 2 +- + zipl/boot/stage3.h | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +--- a/zipl/boot/stage3.c ++++ b/zipl/boot/stage3.c +@@ -292,7 +292,7 @@ void start(void) + /* store subchannel ID into low core and into new kernel space */ + subchannel_id = S390_lowcore.subchannel_id; + *(unsigned int *)__LC_IPLDEV = subchannel_id; +- *(unsigned int *)IPL_DEVICE = subchannel_id; ++ *(unsigned long long *)IPL_DEVICE = subchannel_id; + + /* if valid command line is given, copy it into new kernel space */ + if (_parm_addr != UNSPECIFIED_ADDRESS) { +--- a/zipl/boot/stage3.h ++++ b/zipl/boot/stage3.h +@@ -17,7 +17,7 @@ + + #include "boot/ipl.h" + +-#define IPL_DEVICE 0x10404UL ++#define IPL_DEVICE 0x10400UL + #define INITRD_START 0x10408UL + #define INITRD_SIZE 0x10410UL + #define OLDMEM_BASE 0x10418UL diff --git a/s390-tools-sles15sp2-25-zipl-move-Linux-layout-definitions-into-separate-hea.patch b/s390-tools-sles15sp2-25-zipl-move-Linux-layout-definitions-into-separate-hea.patch new file mode 100644 index 0000000..f556c50 --- /dev/null +++ b/s390-tools-sles15sp2-25-zipl-move-Linux-layout-definitions-into-separate-hea.patch @@ -0,0 +1,109 @@ +Subject: [PATCH] [FEAT VS1804] zipl: move Linux layout definitions into separate header +From: Marc Hartmayer + +Summary: genprotimg: Introduce new tool for the creation of PV images +Description: genprotimg takes a kernel, host-key documents, optionally an + initrd, optionally a file with the kernel command line, and it + generates a single, loadable image file. The image consists of a + concatenation of a plain text boot loader, the encrypted + components for kernel, initrd, and cmdline, and the + integrity-protected PV header, containing metadata necessary for + running the guest in PV mode. It's possible to use this image file + as a kernel for zIPL or for a direct kernel boot using QEMU. +Upstream-ID: 7e37a1d4e0605ea120db18f82d039c055fd5d737 +Problem-ID: VS1804 + +Upstream-Description: + + zipl: move Linux layout definitions into separate header + + Move the Linux layout values to `include/boot/linux_layout.h`. This + allows the reuse of the definitions, e.g. in assembler files, and + later for the creation of linker scripts. + + Reviewed-by: Stefan Haberland + Reviewed-by: Philipp Rudo + Signed-off-by: Marc Hartmayer + Signed-off-by: Jan Höppner + + +Signed-off-by: Marc Hartmayer +--- + include/boot/linux_layout.h | 33 +++++++++++++++++++++++++++++++++ + zipl/boot/stage3.h | 9 ++------- + zipl/include/zipl.h | 3 +-- + 3 files changed, 36 insertions(+), 9 deletions(-) + +--- /dev/null ++++ b/include/boot/linux_layout.h +@@ -0,0 +1,33 @@ ++/* ++ * s390 Linux layout definitions ++ * ++ * Copyright IBM Corp. 2020 ++ * ++ * s390-tools is free software; you can redistribute it and/or modify ++ * it under the terms of the MIT license. See LICENSE for details. ++ */ ++ ++#ifndef LINUX_LAYOUT_H ++#define LINUX_LAYOUT_H ++ ++#include "lib/zt_common.h" ++ ++/* Entry address offsets */ ++#define IMAGE_ENTRY _AC(0x10000, UL) ++#define IMAGE_ENTRY_KDUMP _AC(0x10010, UL) ++ ++/* Parameter address offsets */ ++#define IPL_DEVICE _AC(0x10400, UL) ++#define INITRD_START _AC(0x10408, UL) ++#define INITRD_SIZE _AC(0x10410, UL) ++#define OLDMEM_BASE _AC(0x10418, UL) ++#define OLDMEM_SIZE _AC(0x10420, UL) ++#define COMMAND_LINE _AC(0x10480, UL) ++ ++/* Parameter sizes */ ++#define COMMAND_LINE_SIZE 896 ++ ++ ++#ifndef __ASSEMBLER__ ++#endif /* __ASSEMBLER__ */ ++#endif /* LINUX_LAYOUT_H */ +--- a/zipl/boot/stage3.h ++++ b/zipl/boot/stage3.h +@@ -16,14 +16,9 @@ + #include "s390.h" + + #include "boot/ipl.h" ++#include "boot/linux_layout.h" ++ + +-#define IPL_DEVICE 0x10400UL +-#define INITRD_START 0x10408UL +-#define INITRD_SIZE 0x10410UL +-#define OLDMEM_BASE 0x10418UL +-#define OLDMEM_SIZE 0x10420UL +-#define COMMAND_LINE 0x10480UL +-#define COMMAND_LINE_SIZE 896 + #define COMMAND_LINE_EXTRA 0xE000 + + #define STAGE3_FLAG_SCSI 0x0001000000000000ULL +--- a/zipl/include/zipl.h ++++ b/zipl/include/zipl.h +@@ -14,14 +14,13 @@ + + #include + #include "lib/zt_common.h" ++#include "boot/linux_layout.h" + + #define ZIPL_MAGIC "zIPL" + #define ZIPL_MAGIC_SIZE 4 + #define DISK_LAYOUT_ID 0x00000001 + + #define STAGE3_ENTRY 0xa000UL +-#define IMAGE_ENTRY 0x10000UL +-#define IMAGE_ENTRY_KDUMP 0x10010UL + + #define STAGE2_LOAD_ADDRESS 0x2000UL + #define STAGE3_LOAD_ADDRESS 0xa000UL diff --git a/s390-tools-sles15sp2-26-zipl-tape0-use-constants-defined-in-linux_layout.h.patch b/s390-tools-sles15sp2-26-zipl-tape0-use-constants-defined-in-linux_layout.h.patch new file mode 100644 index 0000000..744dc4d --- /dev/null +++ b/s390-tools-sles15sp2-26-zipl-tape0-use-constants-defined-in-linux_layout.h.patch @@ -0,0 +1,79 @@ +Subject: [PATCH] [FEAT VS1804] zipl: tape0: use constants defined in linux_layout.h +From: Marc Hartmayer + +Summary: genprotimg: Introduce new tool for the creation of PV images +Description: genprotimg takes a kernel, host-key documents, optionally an + initrd, optionally a file with the kernel command line, and it + generates a single, loadable image file. The image consists of a + concatenation of a plain text boot loader, the encrypted + components for kernel, initrd, and cmdline, and the + integrity-protected PV header, containing metadata necessary for + running the guest in PV mode. It's possible to use this image file + as a kernel for zIPL or for a direct kernel boot using QEMU. +Upstream-ID: c871050097ecb2ec83cf3018ea36e01cd22cbe7d +Problem-ID: VS1804 + +Upstream-Description: + + zipl: tape0: use constants defined in linux_layout.h + + Use the constants defined in `linux_layout.h`. Therefore move the + `PARMAREA` address offset to `linux_layout.h` and include the header. + + Reviewed-by: Philipp Rudo + Reviewed-by: Stefan Haberland + Signed-off-by: Marc Hartmayer + Signed-off-by: Jan Höppner + + +Signed-off-by: Marc Hartmayer +--- + include/boot/linux_layout.h | 1 + + zipl/boot/tape0.S | 14 +++----------- + 2 files changed, 4 insertions(+), 11 deletions(-) + +--- a/include/boot/linux_layout.h ++++ b/include/boot/linux_layout.h +@@ -17,6 +17,7 @@ + #define IMAGE_ENTRY_KDUMP _AC(0x10010, UL) + + /* Parameter address offsets */ ++#define PARMAREA _AC(0x10400, UL) + #define IPL_DEVICE _AC(0x10400, UL) + #define INITRD_START _AC(0x10408, UL) + #define INITRD_SIZE _AC(0x10410, UL) +--- a/zipl/boot/tape0.S ++++ b/zipl/boot/tape0.S +@@ -8,29 +8,21 @@ + # + + #include "boot/sigp.h" ++#include "boot/linux_layout.h" + + IPL_BS = 1024 # block size for tape access + IPL_OFF = 0x4000 # temporary kernel load addr +-COMMAND_LINE_SIZE = 896 # max command line length +-KERNEL_OFF = 0x10000 # kernel start code offset ++KERNEL_OFF = IMAGE_ENTRY # kernel start code offset + # relative to image start + __LC_IO_NEW_PSW = 0x1f0 # IO New PSW addr + + +-# Parameter address offsets +- +-PARMAREA = 0x10400 # Parameter area offset +-IPL_DEVICE = 0x10400 # IPL device offset +-INITRD_START = 0x10408 # ramdisk addr offset +-INITRD_SIZE = 0x10410 # ramdisk size offset +-COMMAND_LINE = 0x10480 # command line offset +- + # Default IPL parameter - will be overwritten by zIPL + + RAMDISK_ORIGIN = 0x800000 # default ramdisk load addr + RAMDISK_SIZE = 0x800000 # default ramdisk size + PARMFILE_ADDR = 0x1000 # default parmfile load addr +-KERNEL_ADDR = 0x10000 # default kernel load addr ++KERNEL_ADDR = IMAGE_ENTRY # default kernel load addr + + + .org 0x0 diff --git a/s390-tools-sles15sp2-27-zipl-use-STAGE3_ENTRY-for-STAGE3_LOAD_ADDRESS.patch b/s390-tools-sles15sp2-27-zipl-use-STAGE3_ENTRY-for-STAGE3_LOAD_ADDRESS.patch new file mode 100644 index 0000000..31b649d --- /dev/null +++ b/s390-tools-sles15sp2-27-zipl-use-STAGE3_ENTRY-for-STAGE3_LOAD_ADDRESS.patch @@ -0,0 +1,45 @@ +Subject: [PATCH] [FEAT VS1804] zipl: use STAGE3_ENTRY for STAGE3_LOAD_ADDRESS +From: Marc Hartmayer + +Summary: genprotimg: Introduce new tool for the creation of PV images +Description: genprotimg takes a kernel, host-key documents, optionally an + initrd, optionally a file with the kernel command line, and it + generates a single, loadable image file. The image consists of a + concatenation of a plain text boot loader, the encrypted + components for kernel, initrd, and cmdline, and the + integrity-protected PV header, containing metadata necessary for + running the guest in PV mode. It's possible to use this image file + as a kernel for zIPL or for a direct kernel boot using QEMU. +Upstream-ID: c07104dbc734ec6e55accf1bd2091b251f312ed8 +Problem-ID: VS1804 + +Upstream-Description: + + zipl: use STAGE3_ENTRY for STAGE3_LOAD_ADDRESS + + Use STAGE3_ENTRY for STAGE3_LOAD_ADDRESS as they have the same value + and this makes it more clear that the load address of stage3 is also + its entry point. + + Reviewed-by: Stefan Haberland + Reviewed-by: Philipp Rudo + Signed-off-by: Marc Hartmayer + Signed-off-by: Jan Höppner + + +Signed-off-by: Marc Hartmayer +--- + zipl/include/zipl.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/zipl/include/zipl.h ++++ b/zipl/include/zipl.h +@@ -23,7 +23,7 @@ + #define STAGE3_ENTRY 0xa000UL + + #define STAGE2_LOAD_ADDRESS 0x2000UL +-#define STAGE3_LOAD_ADDRESS 0xa000UL ++#define STAGE3_LOAD_ADDRESS STAGE3_ENTRY + #define IMAGE_LOAD_ADDRESS IMAGE_ENTRY + + #define ADDRESS_LIMIT 0x80000000UL diff --git a/s390-tools-sles15sp2-28-zipl-move-loaders-layout-definitions-into-separate-h.patch b/s390-tools-sles15sp2-28-zipl-move-loaders-layout-definitions-into-separate-h.patch new file mode 100644 index 0000000..e49d0f3 --- /dev/null +++ b/s390-tools-sles15sp2-28-zipl-move-loaders-layout-definitions-into-separate-h.patch @@ -0,0 +1,105 @@ +Subject: [PATCH] [FEAT VS1804] zipl: move loaders layout definitions into separate header +From: Marc Hartmayer + +Summary: genprotimg: Introduce new tool for the creation of PV images +Description: genprotimg takes a kernel, host-key documents, optionally an + initrd, optionally a file with the kernel command line, and it + generates a single, loadable image file. The image consists of a + concatenation of a plain text boot loader, the encrypted + components for kernel, initrd, and cmdline, and the + integrity-protected PV header, containing metadata necessary for + running the guest in PV mode. It's possible to use this image file + as a kernel for zIPL or for a direct kernel boot using QEMU. +Upstream-ID: 97ab8fb4e98c84a89d421c08b392db665125a3c0 +Problem-ID: VS1804 + +Upstream-Description: + + zipl: move loaders layout definitions into separate header + + Move the loaders (stage2/stage3) layout values to + `include/boot/loaders_layout.h` and use the `_AC` macro for the + constants. This allows the reuse of the definitions, e.g. in assembler + files, and later for the creation of linker scripts. + + Reviewed-by: Stefan Haberland + Reviewed-by: Philipp Rudo + Signed-off-by: Marc Hartmayer + Signed-off-by: Jan Höppner + + +Signed-off-by: Marc Hartmayer +--- + include/boot/loaders_layout.h | 32 ++++++++++++++++++++++++++++++++ + zipl/include/zipl.h | 14 +------------- + 2 files changed, 33 insertions(+), 13 deletions(-) + +--- /dev/null ++++ b/include/boot/loaders_layout.h +@@ -0,0 +1,32 @@ ++/* ++ * zipl stage2/stage3 layout definitions ++ * ++ * Copyright IBM Corp. 2020 ++ * ++ * s390-tools is free software; you can redistribute it and/or modify ++ * it under the terms of the MIT license. See LICENSE for details. ++ * ++ */ ++ ++#ifndef LOADERS_LAYOUT_H ++#define LOADERS_LAYOUT_H ++ ++#include "lib/zt_common.h" ++#include "linux_layout.h" ++ ++#define STAGE3_ENTRY _AC(0xa000, UL) ++ ++#define STAGE2_LOAD_ADDRESS _AC(0x2000, UL) ++#define STAGE3_LOAD_ADDRESS STAGE3_ENTRY ++#define IMAGE_LOAD_ADDRESS IMAGE_ENTRY ++ ++#define STAGE3_HEAP_SIZE _AC(0x4000, UL) ++#define STAGE3_HEAP_ADDRESS _AC(0x2000, UL) ++#define STAGE3_STACK_SIZE _AC(0x1000, UL) ++#define STAGE3_STACK_ADDRESS _AC(0xF000, UL) ++#define STAGE3_PARAMS_ADDRESS _AC(0x9000, UL) ++ ++ ++#ifndef __ASSEMBLER__ ++#endif /* __ASSEMBLER__ */ ++#endif /* LOADERS_LAYOUT_H */ +--- a/zipl/include/zipl.h ++++ b/zipl/include/zipl.h +@@ -14,30 +14,18 @@ + + #include + #include "lib/zt_common.h" +-#include "boot/linux_layout.h" ++#include "boot/loaders_layout.h" + + #define ZIPL_MAGIC "zIPL" + #define ZIPL_MAGIC_SIZE 4 + #define DISK_LAYOUT_ID 0x00000001 + +-#define STAGE3_ENTRY 0xa000UL +- +-#define STAGE2_LOAD_ADDRESS 0x2000UL +-#define STAGE3_LOAD_ADDRESS STAGE3_ENTRY +-#define IMAGE_LOAD_ADDRESS IMAGE_ENTRY +- + #define ADDRESS_LIMIT 0x80000000UL + #define ADDRESS_LIMIT_KDUMP 0x2000000UL /* HSA size: 32 MiB */ + #define UNSPECIFIED_ADDRESS -1UL + #define MAXIMUM_PARMLINE_SIZE 0x380UL + #define MAXIMUM_PHYSICAL_BLOCKSIZE 0x1000UL + +-#define STAGE3_HEAP_SIZE 0x4000UL +-#define STAGE3_HEAP_ADDRESS 0x2000UL +-#define STAGE3_STACK_SIZE 0x1000UL +-#define STAGE3_STACK_ADDRESS 0xF000UL +-#define STAGE3_PARAMS_ADDRESS 0x9000UL +- + #define PSW_ADDRESS_MASK 0x000000007fffffffUL + #define PSW_LOAD 0x0008000080000000UL + #define PSW_DISABLED_WAIT 0x000a000000000000UL diff --git a/s390-tools-sles15sp2-29-zipl-s390.h-rename-inline-macro-into-__always_inline.patch b/s390-tools-sles15sp2-29-zipl-s390.h-rename-inline-macro-into-__always_inline.patch new file mode 100644 index 0000000..1835dc1 --- /dev/null +++ b/s390-tools-sles15sp2-29-zipl-s390.h-rename-inline-macro-into-__always_inline.patch @@ -0,0 +1,192 @@ +Subject: [PATCH] [FEAT VS1804] zipl/s390.h: rename `inline` macro into `__always_inline` +From: Marc Hartmayer + +Summary: genprotimg: Introduce new tool for the creation of PV images +Description: genprotimg takes a kernel, host-key documents, optionally an + initrd, optionally a file with the kernel command line, and it + generates a single, loadable image file. The image consists of a + concatenation of a plain text boot loader, the encrypted + components for kernel, initrd, and cmdline, and the + integrity-protected PV header, containing metadata necessary for + running the guest in PV mode. It's possible to use this image file + as a kernel for zIPL or for a direct kernel boot using QEMU. +Upstream-ID: 67e76b8ebd8acb4aef1d22309287776892b7267e +Problem-ID: VS1804 + +Upstream-Description: + + zipl/s390.h: rename `inline` macro into `__always_inline` + + Rename `inline` macro into `__always_inline` so one can differentiate + between the macro and the C keyword. While at it, undefine the + previous `__always_inline` macro so s390.h can be used in combination + with glibc. + + Reviewed-by: Philipp Rudo + Reviewed-by: Stefan Haberland + Signed-off-by: Marc Hartmayer + Signed-off-by: Jan Höppner + + +Signed-off-by: Marc Hartmayer +--- + zipl/boot/s390.h | 39 ++++++++++++++++++++++----------------- + 1 file changed, 22 insertions(+), 17 deletions(-) + +--- a/zipl/boot/s390.h ++++ b/zipl/boot/s390.h +@@ -19,7 +19,12 @@ + #define __pa(x) ((unsigned long)(x)) + #define MIN(x, y) ((x) < (y) ? (x) : (y)) + #define barrier() __asm__ __volatile__("": : :"memory") +-#define inline inline __attribute__((always_inline)) ++/* The Linux kernel (in stddef.h) and glibc (sys/cdefs.h) define ++ * __always_inline. Therefore undefine it first to allow the headers ++ * to be included first. ++ */ ++#undef __always_inline ++#define __always_inline inline __attribute__((always_inline)) + + /* + * Helper macro for exception table entries +@@ -214,7 +219,7 @@ do { \ + libc_stop(reason); \ + } while (0) + +-static inline int page_is_valid(unsigned long addr) ++static __always_inline int page_is_valid(unsigned long addr) + { + unsigned long tmp; + int rc; +@@ -234,7 +239,7 @@ static inline int page_is_valid(unsigned + return rc; + } + +-static inline uint32_t csum_partial(const void *buf, int len, uint32_t sum) ++static __always_inline uint32_t csum_partial(const void *buf, int len, uint32_t sum) + { + register unsigned long reg2 asm("2") = (unsigned long) buf; + register unsigned long reg3 asm("3") = (unsigned long) len; +@@ -262,7 +267,7 @@ static inline uint32_t csum_partial(cons + "i" (low), "i" (high)); \ + }) + +-static inline void __ctl_set_bit(unsigned int cr, unsigned int bit) ++static __always_inline void __ctl_set_bit(unsigned int cr, unsigned int bit) + { + unsigned long reg; + +@@ -282,7 +287,7 @@ enum diag308_subcode { + DIAG308_STORE = 6, + }; + +-static inline int diag308(unsigned long subcode, void *addr) ++static __always_inline int diag308(unsigned long subcode, void *addr) + { + register unsigned long _addr asm("0") = (unsigned long) addr; + register unsigned long _rc asm("1") = 0; +@@ -298,7 +303,7 @@ static inline int diag308(unsigned long + /* + * Store CPU address + */ +-static inline unsigned short stap(void) ++static __always_inline unsigned short stap(void) + { + unsigned short cpu_address; + +@@ -309,7 +314,7 @@ static inline unsigned short stap(void) + /* + * Program the clock comparator + */ +-static inline void set_clock_comparator(uint64_t time) ++static __always_inline void set_clock_comparator(uint64_t time) + { + asm volatile("sckc %0" : : "Q" (time)); + } +@@ -317,7 +322,7 @@ static inline void set_clock_comparator( + /* + * Program the CPU timer + */ +-static inline void set_cpu_timer(uint64_t timer) ++static __always_inline void set_cpu_timer(uint64_t timer) + { + asm volatile("spt %0" : : "Q" (timer)); + } +@@ -325,7 +330,7 @@ static inline void set_cpu_timer(uint64_ + /* + * Get current time (store clock) + */ +-static inline unsigned long long get_tod_clock(void) ++static __always_inline unsigned long long get_tod_clock(void) + { + unsigned long long clk; + +@@ -343,7 +348,7 @@ struct cpuid { + unsigned int unused:16; + } __packed __aligned(8); + +-static inline void get_cpu_id(struct cpuid *ptr) ++static __always_inline void get_cpu_id(struct cpuid *ptr) + { + asm volatile("stidp %0" : "=Q" (*ptr)); + } +@@ -351,7 +356,7 @@ static inline void get_cpu_id(struct cpu + /* + * Check if we run under z/VM + */ +-static inline int is_zvm(void) ++static __always_inline int is_zvm(void) + { + struct cpuid cpuid; + +@@ -369,7 +374,7 @@ typedef struct { + /* + * Save vector registers + */ +-static inline void save_vx_regs(__vector128 *vxrs) ++static __always_inline void save_vx_regs(__vector128 *vxrs) + { + typedef struct { __vector128 _[32]; } addrtype; + +@@ -383,7 +388,7 @@ static inline void save_vx_regs(__vector + /* + * Save vector registers safe + */ +-static inline void save_vx_regs_safe(__vector128 *vxrs) ++static __always_inline void save_vx_regs_safe(__vector128 *vxrs) + { + unsigned long cr0; + +@@ -396,7 +401,7 @@ static inline void save_vx_regs_safe(__v + + #define MAX_FACILITY_BIT (256*8) /* stfle_fac_list has 256 bytes */ + +-static inline int __test_facility(unsigned long nr, void *facilities) ++static __always_inline int __test_facility(unsigned long nr, void *facilities) + { + unsigned char *ptr; + +@@ -411,12 +416,12 @@ static inline int __test_facility(unsign + * That makes it easier to query facility bits with the bit number as + * documented in the Principles of Operation. + */ +-static inline int test_facility(unsigned long nr) ++static __always_inline int test_facility(unsigned long nr) + { + return __test_facility(nr, &S390_lowcore.stfle_fac_list); + } + +-static inline unsigned long __stfle_asm(uint64_t *stfle_fac_list, int size) ++static __always_inline unsigned long __stfle_asm(uint64_t *stfle_fac_list, int size) + { + register unsigned long reg0 asm("0") = size - 1; + +@@ -433,7 +438,7 @@ static inline unsigned long __stfle_asm( + * @stfle_fac_list: array where facility list can be stored + * @size: size of passed in array in double words + */ +-static inline void stfle(uint64_t *stfle_fac_list, int size) ++static __always_inline void stfle(uint64_t *stfle_fac_list, int size) + { + unsigned long nr; + diff --git a/s390-tools-sles15sp2-30-zipl-move-__always_inline-barrier-__pa32-pa-to-zt_co.patch b/s390-tools-sles15sp2-30-zipl-move-__always_inline-barrier-__pa32-pa-to-zt_co.patch new file mode 100644 index 0000000..c59e0d7 --- /dev/null +++ b/s390-tools-sles15sp2-30-zipl-move-__always_inline-barrier-__pa32-pa-to-zt_co.patch @@ -0,0 +1,74 @@ +Subject: [PATCH] [FEAT VS1804] zipl: move __always_inline/barrier/__pa32/pa to zt_common.h +From: Marc Hartmayer + +Summary: genprotimg: Introduce new tool for the creation of PV images +Description: genprotimg takes a kernel, host-key documents, optionally an + initrd, optionally a file with the kernel command line, and it + generates a single, loadable image file. The image consists of a + concatenation of a plain text boot loader, the encrypted + components for kernel, initrd, and cmdline, and the + integrity-protected PV header, containing metadata necessary for + running the guest in PV mode. It's possible to use this image file + as a kernel for zIPL or for a direct kernel boot using QEMU. +Upstream-ID: 24fe8c1d1b75185f341ec2d0efc6c34f0b9263f1 +Problem-ID: VS1804 + +Upstream-Description: + + zipl: move __always_inline/barrier/__pa32/pa to zt_common.h + + Move `__always_inline/barrier/__pa32/pa` to `lib/zt_common.h` as this + is non-architecture dependent code. + + Reviewed-by: Philipp Rudo + Reviewed-by: Stefan Haberland + Signed-off-by: Marc Hartmayer + Signed-off-by: Jan Höppner + + +Signed-off-by: Marc Hartmayer +--- + include/lib/zt_common.h | 12 ++++++++++++ + zipl/boot/s390.h | 9 --------- + 2 files changed, 12 insertions(+), 9 deletions(-) + +--- a/include/lib/zt_common.h ++++ b/include/lib/zt_common.h +@@ -55,6 +55,18 @@ + #define __may_alias __attribute__((may_alias)) + #define __section(x) __attribute__((__section__(#x))) + #define __noinline __attribute__((__noinline__)) ++/* The Linux kernel (in stddef.h) and glibc (sys/cdefs.h) define ++ * __always_inline. Therefore undefine it first to allow the headers ++ * to be included first. ++ */ ++#undef __always_inline ++#define __always_inline inline __attribute__((always_inline)) ++ ++#define __pa32(x) ((uint32_t)(unsigned long)(x)) ++#define __pa(x) ((unsigned long)(x)) ++ ++#define barrier() __asm__ __volatile__("": : :"memory") ++ + + typedef unsigned long long u64; + typedef signed long long s64; +--- a/zipl/boot/s390.h ++++ b/zipl/boot/s390.h +@@ -15,16 +15,7 @@ + #include "libc.h" + #include "boot/sigp.h" + +-#define __pa32(x) ((uint32_t)(unsigned long)(x)) +-#define __pa(x) ((unsigned long)(x)) + #define MIN(x, y) ((x) < (y) ? (x) : (y)) +-#define barrier() __asm__ __volatile__("": : :"memory") +-/* The Linux kernel (in stddef.h) and glibc (sys/cdefs.h) define +- * __always_inline. Therefore undefine it first to allow the headers +- * to be included first. +- */ +-#undef __always_inline +-#define __always_inline inline __attribute__((always_inline)) + + /* + * Helper macro for exception table entries diff --git a/s390-tools-sles15sp2-31-zipl-make-BLK_PWRT-unsigned-int.patch b/s390-tools-sles15sp2-31-zipl-make-BLK_PWRT-unsigned-int.patch new file mode 100644 index 0000000..e90f038 --- /dev/null +++ b/s390-tools-sles15sp2-31-zipl-make-BLK_PWRT-unsigned-int.patch @@ -0,0 +1,44 @@ +Subject: [PATCH] [FEAT VS1804] zipl: make BLK_PWRT unsigned int +From: Marc Hartmayer + +Summary: genprotimg: Introduce new tool for the creation of PV images +Description: genprotimg takes a kernel, host-key documents, optionally an + initrd, optionally a file with the kernel command line, and it + generates a single, loadable image file. The image consists of a + concatenation of a plain text boot loader, the encrypted + components for kernel, initrd, and cmdline, and the + integrity-protected PV header, containing metadata necessary for + running the guest in PV mode. It's possible to use this image file + as a kernel for zIPL or for a direct kernel boot using QEMU. +Upstream-ID: 2e28291c75d73b92921f7769eaa803fe3222f383 +Problem-ID: VS1804 + +Upstream-Description: + + zipl: make BLK_PWRT unsigned int + + Otherwise there might be a compiler warning when using 'MIN(bl_count, + BLK_PWRT)'. + + Reviewed-by: Philipp Rudo + Reviewed-by: Stefan Haberland + Signed-off-by: Marc Hartmayer + Signed-off-by: Jan Höppner + + +Signed-off-by: Marc Hartmayer +--- + zipl/boot/fba2dump.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/zipl/boot/fba2dump.c ++++ b/zipl/boot/fba2dump.c +@@ -14,7 +14,7 @@ + #include "fba.h" + #include "stage2dump.h" + +-#define BLK_PWRT 64 /* Blocks per write */ ++#define BLK_PWRT 64U /* Blocks per write */ + #define BLK_SIZE 0x200 /* FBA block size */ + #define BLK_PER_PAGE (PAGE_SIZE / BLK_SIZE) /* FBA blocks per page */ + diff --git a/s390-tools-sles15sp2-32-Consolidate-MIN-and-MAX-macros.patch b/s390-tools-sles15sp2-32-Consolidate-MIN-and-MAX-macros.patch new file mode 100644 index 0000000..ddab384 --- /dev/null +++ b/s390-tools-sles15sp2-32-Consolidate-MIN-and-MAX-macros.patch @@ -0,0 +1,105 @@ +Subject: [PATCH] [FEAT VS1804] Consolidate MIN and MAX macros +From: Marc Hartmayer + +Summary: genprotimg: Introduce new tool for the creation of PV images +Description: genprotimg takes a kernel, host-key documents, optionally an + initrd, optionally a file with the kernel command line, and it + generates a single, loadable image file. The image consists of a + concatenation of a plain text boot loader, the encrypted + components for kernel, initrd, and cmdline, and the + integrity-protected PV header, containing metadata necessary for + running the guest in PV mode. It's possible to use this image file + as a kernel for zIPL or for a direct kernel boot using QEMU. +Upstream-ID: c55ceabc6726a7806922d288149003661f673a2f +Problem-ID: VS1804 + +Upstream-Description: + + Consolidate MIN and MAX macros + + Consolidate MIN and MAX macros and make sure it can be used in + combination with glib. + + Reviewed-by: Philipp Rudo + Reviewed-by: Stefan Haberland + Acked-by: Jan Höppner + Signed-off-by: Marc Hartmayer + Signed-off-by: Jan Höppner + + +Signed-off-by: Marc Hartmayer +--- + include/lib/util_base.h | 17 +---------------- + include/lib/zt_common.h | 17 +++++++++++++++++ + zipl/boot/s390.h | 1 - + 3 files changed, 18 insertions(+), 17 deletions(-) + +--- a/include/lib/util_base.h ++++ b/include/lib/util_base.h +@@ -14,6 +14,7 @@ + + #include + #include ++#include "zt_common.h" + + void util_hexdump(FILE *fh, const char *tag, const void *data, int cnt); + void util_hexdump_grp(FILE *fh, const char *tag, const void *data, int group, +@@ -22,22 +23,6 @@ void util_print_indented(const char *str + + #define UTIL_ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0])) + +-#define MIN(x, y) \ +-({ \ +- __typeof__(x) _x = (x); \ +- __typeof__(y) _y = (y); \ +- \ +- _x < _y ? _x : _y; \ +-}) +- +-#define MAX(x, y) \ +-({ \ +- __typeof__(x) _x = (x); \ +- __typeof__(y) _y = (y); \ +- \ +- _x > _y ? _x : _y; \ +-}) +- + static inline void util_ptr_vec_free(void **ptr_vec, int count) + { + int i; +--- a/include/lib/zt_common.h ++++ b/include/lib/zt_common.h +@@ -67,6 +67,23 @@ + + #define barrier() __asm__ __volatile__("": : :"memory") + ++#undef MIN ++#define MIN(x, y) \ ++ ({ \ ++ __typeof__(x) _x = (x); \ ++ __typeof__(y) _y = (y); \ ++ \ ++ _x < _y ? _x : _y; \ ++ }) ++ ++#undef MAX ++#define MAX(x, y) \ ++ ({ \ ++ __typeof__(x) _x = (x); \ ++ __typeof__(y) _y = (y); \ ++ \ ++ _x > _y ? _x : _y; \ ++ }) + + typedef unsigned long long u64; + typedef signed long long s64; +--- a/zipl/boot/s390.h ++++ b/zipl/boot/s390.h +@@ -15,7 +15,6 @@ + #include "libc.h" + #include "boot/sigp.h" + +-#define MIN(x, y) ((x) < (y) ? (x) : (y)) + + /* + * Helper macro for exception table entries diff --git a/s390-tools-sles15sp2-33-zipl-remove-libc.h-include-in-s390.h.patch b/s390-tools-sles15sp2-33-zipl-remove-libc.h-include-in-s390.h.patch new file mode 100644 index 0000000..1bc0ab3 --- /dev/null +++ b/s390-tools-sles15sp2-33-zipl-remove-libc.h-include-in-s390.h.patch @@ -0,0 +1,76 @@ +Subject: [PATCH] [FEAT VS1804] zipl: remove libc.h include in s390.h +From: Marc Hartmayer + +Summary: genprotimg: Introduce new tool for the creation of PV images +Description: genprotimg takes a kernel, host-key documents, optionally an + initrd, optionally a file with the kernel command line, and it + generates a single, loadable image file. The image consists of a + concatenation of a plain text boot loader, the encrypted + components for kernel, initrd, and cmdline, and the + integrity-protected PV header, containing metadata necessary for + running the guest in PV mode. It's possible to use this image file + as a kernel for zIPL or for a direct kernel boot using QEMU. +Upstream-ID: f454c6825f5087cf671d0dfbe96f7f3d148569d6 +Problem-ID: VS1804 + +Upstream-Description: + + zipl: remove libc.h include in s390.h + + This allows the use of s390.h in combination with other libc + implementations than our minimal libc, e.g. with glibc. + + Reviewed-by: Philipp Rudo + Reviewed-by: Stefan Haberland + Signed-off-by: Marc Hartmayer + Signed-off-by: Jan Höppner + + +Signed-off-by: Marc Hartmayer +--- + zipl/boot/s390.h | 1 - + zipl/boot/sclp.c | 1 + + zipl/boot/sclp_stage3.c | 1 + + zipl/boot/stage2dump.c | 1 + + 4 files changed, 3 insertions(+), 1 deletion(-) + +--- a/zipl/boot/s390.h ++++ b/zipl/boot/s390.h +@@ -12,7 +12,6 @@ + #define S390_H + + #include "lib/zt_common.h" +-#include "libc.h" + #include "boot/sigp.h" + + +--- a/zipl/boot/sclp.c ++++ b/zipl/boot/sclp.c +@@ -9,6 +9,7 @@ + * it under the terms of the MIT license. See LICENSE for details. + */ + ++#include "libc.h" + #include "error.h" + #include "s390.h" + #include "sclp.h" +--- a/zipl/boot/sclp_stage3.c ++++ b/zipl/boot/sclp_stage3.c +@@ -9,6 +9,7 @@ + * it under the terms of the MIT license. See LICENSE for details. + */ + ++#include "libc.h" + #include "sclp.h" + #include "sclp_stage3.h" + +--- a/zipl/boot/stage2dump.c ++++ b/zipl/boot/stage2dump.c +@@ -13,6 +13,7 @@ + + #include "lib/zt_common.h" + ++#include "libc.h" + #include "error.h" + #include "sclp.h" + #include "stage2dump.h" diff --git a/s390-tools-sles15sp2-34-zipl-move-s390.h-to-include-boot-s390.h.patch b/s390-tools-sles15sp2-34-zipl-move-s390.h-to-include-boot-s390.h.patch new file mode 100644 index 0000000..12c7097 --- /dev/null +++ b/s390-tools-sles15sp2-34-zipl-move-s390.h-to-include-boot-s390.h.patch @@ -0,0 +1,1129 @@ +Subject: [PATCH] [FEAT VS1804] zipl: move s390.h to include/boot/s390.h +From: Marc Hartmayer + +Summary: genprotimg: Introduce new tool for the creation of PV images +Description: genprotimg takes a kernel, host-key documents, optionally an + initrd, optionally a file with the kernel command line, and it + generates a single, loadable image file. The image consists of a + concatenation of a plain text boot loader, the encrypted + components for kernel, initrd, and cmdline, and the + integrity-protected PV header, containing metadata necessary for + running the guest in PV mode. It's possible to use this image file + as a kernel for zIPL or for a direct kernel boot using QEMU. +Upstream-ID: b83c8944f195117609a36f383f32377014e34c31 +Problem-ID: VS1804 + +Upstream-Description: + + zipl: move s390.h to include/boot/s390.h + + Now that we made sure that s390.h can be used with our minimal libc + implementation and glibc move s390.h to `include/boot/s390.h`. While + at it, make sure that s390.h is assembler compatible as it will be + used later in the PV boot loader and include s390.h in ipl.h as + PAGE_SIZE is used there. + + Reviewed-by: Philipp Rudo + Reviewed-by: Stefan Haberland + Signed-off-by: Marc Hartmayer + Signed-off-by: Jan Höppner + + +Signed-off-by: Marc Hartmayer +--- + include/boot/ipl.h | 1 + include/boot/s390.h | 452 +++++++++++++++++++++++++++++++++++++++++++++++++ + zipl/boot/cio.c | 2 + zipl/boot/cio.h | 2 + zipl/boot/eckd2.c | 2 + zipl/boot/eckd2dump.c | 2 + zipl/boot/fba2.c | 2 + zipl/boot/kdump.c | 2 + zipl/boot/kdump.h | 2 + zipl/boot/s390.h | 449 ------------------------------------------------ + zipl/boot/sclp.c | 2 + zipl/boot/sclp.h | 2 + zipl/boot/stage2.c | 2 + zipl/boot/stage2.h | 3 + zipl/boot/stage2dump.h | 2 + zipl/boot/stage3.c | 2 + zipl/boot/stage3.h | 2 + 17 files changed, 467 insertions(+), 464 deletions(-) + +--- a/include/boot/ipl.h ++++ b/include/boot/ipl.h +@@ -11,6 +11,7 @@ + #define IPL_H + + #include "lib/zt_common.h" ++#include "s390.h" + + #define IPL_FLAG_SECURE 0x40 + +--- /dev/null ++++ b/include/boot/s390.h +@@ -0,0 +1,452 @@ ++/* ++ * s390 related definitions and functions. ++ * ++ * Copyright IBM Corp. 2013, 2020 ++ * ++ * s390-tools is free software; you can redistribute it and/or modify ++ * it under the terms of the MIT license. See LICENSE for details. ++ */ ++ ++#ifndef S390_H ++#define S390_H ++ ++#include "lib/zt_common.h" ++#include "boot/sigp.h" ++ ++#define __LC_IPLDEV 0x0c6c ++#define __LC_OS_INFO 0x0e18 ++ ++#define PAGE_SIZE _AC(4096, UL) ++ ++ ++#ifndef __ASSEMBLER__ ++ ++/* ++ * Helper macro for exception table entries ++ */ ++#define EX_TABLE(_fault, _target) \ ++ ".section .ex_table,\"a\"\n" \ ++ ".align 4\n" \ ++ ".long (" #_fault ")\n" \ ++ ".long (" #_target ")\n" \ ++ ".previous\n" ++ ++struct psw_t { ++ uint64_t mask; ++ uint64_t addr; ++} __aligned(8); ++ ++struct psw32_t { ++ uint32_t mask; ++ uint32_t addr; ++} __aligned(8); ++ ++void load_wait_psw(uint64_t, struct psw_t *); ++ ++struct _lowcore { ++ uint8_t pad_0x0000[0x0014-0x0000]; /* 0x0000 */ ++ uint32_t ipl_parmblock_ptr; /* 0x0014 */ ++ uint8_t pad_0x0018[0x0080-0x0018]; /* 0x0018 */ ++ uint32_t ext_params; /* 0x0080 */ ++ uint16_t ext_cpu_addr; /* 0x0084 */ ++ uint16_t ext_int_code; /* 0x0086 */ ++ uint16_t svc_ilc; /* 0x0088 */ ++ uint16_t svc_code; /* 0x008a */ ++ uint16_t pgm_ilc; /* 0x008c */ ++ uint16_t pgm_code; /* 0x008e */ ++ uint32_t data_exc_code; /* 0x0090 */ ++ uint16_t mon_class_num; /* 0x0094 */ ++ uint16_t per_perc_atmid; /* 0x0096 */ ++ uint64_t per_address; /* 0x0098 */ ++ uint8_t exc_access_id; /* 0x00a0 */ ++ uint8_t per_access_id; /* 0x00a1 */ ++ uint8_t op_access_id; /* 0x00a2 */ ++ uint8_t ar_access_id; /* 0x00a3 */ ++ uint8_t pad_0x00a4[0x00a8-0x00a4]; /* 0x00a4 */ ++ uint64_t trans_exc_code; /* 0x00a8 */ ++ uint64_t monitor_code; /* 0x00b0 */ ++ uint16_t subchannel_id; /* 0x00b8 */ ++ uint16_t subchannel_nr; /* 0x00ba */ ++ uint32_t io_int_parm; /* 0x00bc */ ++ uint32_t io_int_word; /* 0x00c0 */ ++ uint8_t pad_0x00c4[0x00c8-0x00c4]; /* 0x00c4 */ ++ uint32_t stfl_fac_list; /* 0x00c8 */ ++ uint8_t pad_0x00cc[0x00e8-0x00cc]; /* 0x00cc */ ++ uint32_t mcck_interruption_code[2]; /* 0x00e8 */ ++ uint8_t pad_0x00f0[0x00f4-0x00f0]; /* 0x00f0 */ ++ uint32_t external_damage_code; /* 0x00f4 */ ++ uint64_t failing_storage_address; /* 0x00f8 */ ++ uint8_t pad_0x0100[0x0110-0x0100]; /* 0x0100 */ ++ uint64_t breaking_event_addr; /* 0x0110 */ ++ uint8_t pad_0x0118[0x0120-0x0118]; /* 0x0118 */ ++ struct psw_t restart_old_psw; /* 0x0120 */ ++ struct psw_t external_old_psw; /* 0x0130 */ ++ struct psw_t svc_old_psw; /* 0x0140 */ ++ struct psw_t program_old_psw; /* 0x0150 */ ++ struct psw_t mcck_old_psw; /* 0x0160 */ ++ struct psw_t io_old_psw; /* 0x0170 */ ++ uint8_t pad_0x0180[0x01a0-0x0180]; /* 0x0180 */ ++ struct psw_t restart_psw; /* 0x01a0 */ ++ struct psw_t external_new_psw; /* 0x01b0 */ ++ struct psw_t svc_new_psw; /* 0x01c0 */ ++ struct psw_t program_new_psw; /* 0x01d0 */ ++ struct psw_t mcck_new_psw; /* 0x01e0 */ ++ struct psw_t io_new_psw; /* 0x01f0 */ ++ ++ /* Save areas. */ ++ uint64_t save_area_sync[8]; /* 0x0200 */ ++ uint64_t save_area_async[8]; /* 0x0240 */ ++ uint64_t save_area_restart[1]; /* 0x0280 */ ++ uint8_t pad_0x0288[0x0290-0x0288]; /* 0x0288 */ ++ ++ /* Return psws. */ ++ struct psw_t return_psw; /* 0x0290 */ ++ struct psw_t return_mcck_psw; /* 0x02a0 */ ++ ++ /* CPU accounting and timing values. */ ++ uint64_t sync_enter_timer; /* 0x02b0 */ ++ uint64_t async_enter_timer; /* 0x02b8 */ ++ uint64_t mcck_enter_timer; /* 0x02c0 */ ++ uint64_t exit_timer; /* 0x02c8 */ ++ uint64_t user_timer; /* 0x02d0 */ ++ uint64_t system_timer; /* 0x02d8 */ ++ uint64_t steal_timer; /* 0x02e0 */ ++ uint64_t last_update_timer; /* 0x02e8 */ ++ uint64_t last_update_clock; /* 0x02f0 */ ++ uint64_t int_clock; /* 0x02f8 */ ++ uint64_t mcck_clock; /* 0x0300 */ ++ uint64_t clock_comparator; /* 0x0308 */ ++ ++ /* Current process. */ ++ uint64_t current_task; /* 0x0310 */ ++ uint64_t thread_info; /* 0x0318 */ ++ uint64_t kernel_stack; /* 0x0320 */ ++ ++ /* Interrupt, panic and restart stack. */ ++ uint64_t async_stack; /* 0x0328 */ ++ uint64_t panic_stack; /* 0x0330 */ ++ uint64_t restart_stack; /* 0x0338 */ ++ ++ /* Restart function and parameter. */ ++ uint64_t restart_fn; /* 0x0340 */ ++ uint64_t restart_data; /* 0x0348 */ ++ uint64_t restart_source; /* 0x0350 */ ++ ++ /* Address space pointer. */ ++ uint64_t kernel_asce; /* 0x0358 */ ++ uint64_t user_asce; /* 0x0360 */ ++ uint64_t current_pid; /* 0x0368 */ ++ ++ /* SMP info area */ ++ uint32_t cpu_nr; /* 0x0370 */ ++ uint32_t softirq_pending; /* 0x0374 */ ++ uint64_t percpu_offset; /* 0x0378 */ ++ uint64_t vdso_per_cpu_data; /* 0x0380 */ ++ uint64_t machine_flags; /* 0x0388 */ ++ uint64_t ftrace_func; /* 0x0390 */ ++ uint64_t gmap; /* 0x0398 */ ++ uint8_t pad_0x03a0[0x0400-0x03a0]; /* 0x03a0 */ ++ ++ /* Interrupt response block. */ ++ uint8_t irb[64]; /* 0x0400 */ ++ ++ /* Per cpu primary space access list */ ++ uint32_t paste[16]; /* 0x0440 */ ++ ++ uint8_t pad_0x0480[0x0e00-0x0480]; /* 0x0480 */ ++ ++ /* ++ * 0xe00 contains the address of the IPL Parameter Information ++ * block. Dump tools need IPIB for IPL after dump. ++ * Note: do not change the position of any fields in 0x0e00-0x0f00 ++ */ ++ uint64_t ipib; /* 0x0e00 */ ++ uint32_t ipib_checksum; /* 0x0e08 */ ++ uint64_t vmcore_info; /* 0x0e0c */ ++ uint8_t pad_0x0e14[0x0e18-0x0e14]; /* 0x0e14 */ ++ uint64_t os_info; /* 0x0e18 */ ++ uint8_t pad_0x0e20[0x0f00-0x0e20]; /* 0x0e20 */ ++ ++ /* Extended facility list */ ++ uint64_t stfle_fac_list[32]; /* 0x0f00 */ ++ uint8_t pad_0x1000[0x11b0-0x1000]; /* 0x1000 */ ++ uint64_t vector_save_area_addr; /* 0x11b0 */ ++ /* 64 bit extparam used for pfault/diag 250: defined by architecture */ ++ uint64_t ext_params2; /* 0x11B8 */ ++ uint8_t pad_0x11c0[0x1200-0x11C0]; /* 0x11C0 */ ++ ++ /* CPU register save area: defined by architecture */ ++ uint64_t floating_pt_save_area[16]; /* 0x1200 */ ++ uint64_t gpregs_save_area[16]; /* 0x1280 */ ++ struct psw_t psw_save_area; /* 0x1300 */ ++ uint8_t pad_0x1310[0x1318-0x1310]; /* 0x1310 */ ++ uint32_t prefixreg_save_area; /* 0x1318 */ ++ uint32_t fpt_creg_save_area; /* 0x131c */ ++ uint8_t pad_0x1320[0x1324-0x1320]; /* 0x1320 */ ++ uint32_t tod_progreg_save_area; /* 0x1324 */ ++ uint32_t cpu_timer_save_area[2]; /* 0x1328 */ ++ uint32_t clock_comp_save_area[2]; /* 0x1330 */ ++ uint8_t pad_0x1338[0x1340-0x1338]; /* 0x1338 */ ++ uint32_t access_regs_save_area[16]; /* 0x1340 */ ++ uint64_t cregs_save_area[16]; /* 0x1380 */ ++ uint8_t pad_0x1400[0x1800-0x1400]; /* 0x1400 */ ++ ++ /* Transaction abort diagnostic block */ ++ uint8_t pgm_tdb[256]; /* 0x1800 */ ++ ++ /* align to the top of the prefix area */ ++ uint8_t pad_0x1900[0x2000-0x1900]; /* 0x1900 */ ++} __packed __aligned(8192); ++ ++#define S390_lowcore (*((struct _lowcore *) 0)) ++ ++ ++void panic_notify(unsigned long reason); ++ ++#define panic(reason, x...) \ ++do { \ ++ printf(x); \ ++ panic_notify(reason); \ ++ libc_stop(reason); \ ++} while (0) ++ ++static __always_inline int page_is_valid(unsigned long addr) ++{ ++ unsigned long tmp; ++ int rc; ++ ++ asm volatile( ++ "0: ic %1,%2\n" ++ "1: lhi %0,1\n" ++ "2:\n" ++ ".pushsection .fixup, \"ax\"\n" ++ "3: xr %0,%0\n" ++ " jg 2b\n" ++ ".popsection\n" ++ EX_TABLE(0b, 3b) EX_TABLE(1b, 3b) ++ : "=d" (rc), "=d" (tmp) ++ : "Q" (*(unsigned long *) addr) ++ : "cc"); ++ return rc; ++} ++ ++static __always_inline uint32_t csum_partial(const void *buf, int len, uint32_t sum) ++{ ++ register unsigned long reg2 asm("2") = (unsigned long) buf; ++ register unsigned long reg3 asm("3") = (unsigned long) len; ++ ++ asm volatile( ++ "0: cksm %0,%1\n" /* do checksum on longs */ ++ " jo 0b\n" ++ : "+d" (sum), "+d" (reg2), "+d" (reg3) : : "cc", "memory"); ++ return sum; ++} ++ ++#define __ctl_store(array, low, high) ({ \ ++ typedef struct { char _[sizeof(array)]; } __may_alias addrtype;\ ++ asm volatile( \ ++ " stctg %1,%2,%0\n" \ ++ : "=Q" (*(addrtype *)(&array)) \ ++ : "i" (low), "i" (high)); \ ++}) ++ ++#define __ctl_load(array, low, high) ({ \ ++ typedef struct { char _[sizeof(array)]; } __may_alias addrtype; \ ++ asm volatile( \ ++ " lctlg %1,%2,%0\n" \ ++ : : "Q" (*(addrtype *)(&array)), \ ++ "i" (low), "i" (high)); \ ++}) ++ ++static __always_inline void __ctl_set_bit(unsigned int cr, unsigned int bit) ++{ ++ unsigned long reg; ++ ++ __ctl_store(reg, cr, cr); ++ reg |= 1UL << bit; ++ __ctl_load(reg, cr, cr); ++} ++ ++/* ++ * DIAG 308 support ++ */ ++enum diag308_subcode { ++ DIAG308_REL_HSA = 2, ++ DIAG308_IPL = 3, ++ DIAG308_DUMP = 4, ++ DIAG308_SET = 5, ++ DIAG308_STORE = 6, ++}; ++ ++static __always_inline int diag308(unsigned long subcode, void *addr) ++{ ++ register unsigned long _addr asm("0") = (unsigned long) addr; ++ register unsigned long _rc asm("1") = 0; ++ ++ asm volatile( ++ " diag %0,%2,0x308\n" ++ "0:\n" ++ : "+d" (_addr), "+d" (_rc) ++ : "d" (subcode) : "cc", "memory"); ++ return _rc; ++} ++ ++/* ++ * Store CPU address ++ */ ++static __always_inline unsigned short stap(void) ++{ ++ unsigned short cpu_address; ++ ++ asm volatile("stap %0" : "=m" (cpu_address)); ++ return cpu_address; ++} ++ ++/* ++ * Program the clock comparator ++ */ ++static __always_inline void set_clock_comparator(uint64_t time) ++{ ++ asm volatile("sckc %0" : : "Q" (time)); ++} ++ ++/* ++ * Program the CPU timer ++ */ ++static __always_inline void set_cpu_timer(uint64_t timer) ++{ ++ asm volatile("spt %0" : : "Q" (timer)); ++} ++ ++/* ++ * Get current time (store clock) ++ */ ++static __always_inline unsigned long long get_tod_clock(void) ++{ ++ unsigned long long clk; ++ ++ asm volatile("stck %0" : "=Q" (clk) : : "cc"); ++ return clk; ++} ++ ++/* ++ * Get ID of current CPU ++ */ ++struct cpuid { ++ unsigned int version:8; ++ unsigned int ident:24; ++ unsigned int machine:16; ++ unsigned int unused:16; ++} __packed __aligned(8); ++ ++static __always_inline void get_cpu_id(struct cpuid *ptr) ++{ ++ asm volatile("stidp %0" : "=Q" (*ptr)); ++} ++ ++/* ++ * Check if we run under z/VM ++ */ ++static __always_inline int is_zvm(void) ++{ ++ struct cpuid cpuid; ++ ++ get_cpu_id(&cpuid); ++ return cpuid.version == 0xff; ++} ++ ++/* ++ * Vector register definition ++ */ ++typedef struct { ++ uint32_t u[4]; ++} __vector128; ++ ++/* ++ * Save vector registers ++ */ ++static __always_inline void save_vx_regs(__vector128 *vxrs) ++{ ++ typedef struct { __vector128 _[32]; } addrtype; ++ ++ asm volatile( ++ " la 1,%0\n" ++ " .word 0xe70f,0x1000,0x003e\n" /* vstm 0,15,0(1) */ ++ " .word 0xe70f,0x1100,0x0c3e\n" /* vstm 16,31,256(1) */ ++ : "=Q" (*(addrtype *) vxrs) : : "1"); ++} ++ ++/* ++ * Save vector registers safe ++ */ ++static __always_inline void save_vx_regs_safe(__vector128 *vxrs) ++{ ++ unsigned long cr0; ++ ++ __ctl_store(cr0, 0, 0); ++ __ctl_set_bit(0, 17); ++ __ctl_set_bit(0, 18); /* AFP-register-control */ ++ save_vx_regs(vxrs); ++ __ctl_load(cr0, 0, 0); ++} ++ ++#define MAX_FACILITY_BIT (256*8) /* stfle_fac_list has 256 bytes */ ++ ++static __always_inline int __test_facility(unsigned long nr, void *facilities) ++{ ++ unsigned char *ptr; ++ ++ if (nr >= MAX_FACILITY_BIT) ++ return 0; ++ ptr = (unsigned char *) facilities + (nr >> 3); ++ return (*ptr & (0x80 >> (nr & 7))) != 0; ++} ++ ++/* ++ * The test_facility function uses the bit odering where the MSB is bit 0. ++ * That makes it easier to query facility bits with the bit number as ++ * documented in the Principles of Operation. ++ */ ++static __always_inline int test_facility(unsigned long nr) ++{ ++ return __test_facility(nr, &S390_lowcore.stfle_fac_list); ++} ++ ++static __always_inline unsigned long __stfle_asm(uint64_t *stfle_fac_list, int size) ++{ ++ register unsigned long reg0 asm("0") = size - 1; ++ ++ asm volatile( ++ ".insn s,0xb2b00000,0(%1)" /* stfle */ ++ : "+d" (reg0) ++ : "a" (stfle_fac_list) ++ : "memory", "cc"); ++ return reg0; ++} ++ ++/** ++ * stfle - Store facility list extended ++ * @stfle_fac_list: array where facility list can be stored ++ * @size: size of passed in array in double words ++ */ ++static __always_inline void stfle(uint64_t *stfle_fac_list, int size) ++{ ++ unsigned long nr; ++ ++ asm volatile( ++ " .insn s,0xb2b10000,0(0)\n" /* stfl */ ++ "0:\n" ++ EX_TABLE(0b, 0b) ++ : "+m" (S390_lowcore.stfl_fac_list)); ++ nr = 4; /* bytes stored by stfl */ ++ memcpy(stfle_fac_list, &S390_lowcore.stfl_fac_list, 4); ++ if (S390_lowcore.stfl_fac_list & 0x01000000) { ++ /* More facility bits available with stfle */ ++ nr = __stfle_asm(stfle_fac_list, size); ++ nr = MIN((nr + 1) * 8, size * 8UL); ++ } ++ memset((char *) stfle_fac_list + nr, 0, size * 8 - nr); ++} ++ ++#endif /* __ASSEMBLER__ */ ++#endif /* S390_H */ +--- a/zipl/boot/cio.c ++++ b/zipl/boot/cio.c +@@ -12,7 +12,7 @@ + #include "cio.h" + #include "error.h" + #include "libc.h" +-#include "s390.h" ++#include "boot/s390.h" + + static unsigned long initial_lpm = 0x00; + static const char *msg_essch = "Start subchannel failed"; +--- a/zipl/boot/cio.h ++++ b/zipl/boot/cio.h +@@ -12,7 +12,7 @@ + #define CIO_H + + #include "libc.h" +-#include "s390.h" ++#include "boot/s390.h" + + /* Condition codes */ + #define CC_INITIATED 0 +--- a/zipl/boot/eckd2.c ++++ b/zipl/boot/eckd2.c +@@ -10,7 +10,7 @@ + */ + + #include "eckd.h" +-#include "s390.h" ++#include "boot/s390.h" + #include "stage2.h" + + int extract_length(void *data) +--- a/zipl/boot/eckd2dump.c ++++ b/zipl/boot/eckd2dump.c +@@ -12,7 +12,7 @@ + #include "cio.h" + #include "eckd2dump.h" + #include "error.h" +-#include "s390.h" ++#include "boot/s390.h" + #include "stage2dump.h" + + #define ECKD_CCW_LOCATE_RECORD 0x47 +--- a/zipl/boot/fba2.c ++++ b/zipl/boot/fba2.c +@@ -11,7 +11,7 @@ + + #include "fba.h" + #include "libc.h" +-#include "s390.h" ++#include "boot/s390.h" + + int extract_length(void *data) { + struct linear_blockptr *blockptr = (struct linear_blockptr *)data; +--- a/zipl/boot/kdump.c ++++ b/zipl/boot/kdump.c +@@ -13,7 +13,7 @@ + #include "kdump.h" + #include "libc.h" + #include "menu.h" +-#include "s390.h" ++#include "boot/s390.h" + + void kdump_failed(unsigned long reason) + { +--- a/zipl/boot/kdump.h ++++ b/zipl/boot/kdump.h +@@ -14,7 +14,7 @@ + #define KDUMP_H + + #include "libc.h" +-#include "s390.h" ++#include "boot/s390.h" + + #define OS_INFO_VERSION_MAJOR_SUPPORTED 1 + #define OS_INFO_MAGIC 0x4f53494e464f535aULL /* OSINFOSZ */ +--- a/zipl/boot/s390.h ++++ /dev/null +@@ -1,449 +0,0 @@ +-/* +- * zipl - zSeries Initial Program Loader tool +- * +- * System z specific functions +- * +- * Copyright IBM Corp. 2013, 2017 +- * +- * s390-tools is free software; you can redistribute it and/or modify +- * it under the terms of the MIT license. See LICENSE for details. +- */ +-#ifndef S390_H +-#define S390_H +- +-#include "lib/zt_common.h" +-#include "boot/sigp.h" +- +- +-/* +- * Helper macro for exception table entries +- */ +-#define EX_TABLE(_fault, _target) \ +- ".section .ex_table,\"a\"\n" \ +- ".align 4\n" \ +- ".long (" #_fault ")\n" \ +- ".long (" #_target ")\n" \ +- ".previous\n" +- +-struct psw_t { +- uint64_t mask; +- uint64_t addr; +-} __aligned(8); +- +-struct psw32_t { +- uint32_t mask; +- uint32_t addr; +-} __aligned(8); +- +-void load_wait_psw(uint64_t, struct psw_t *); +- +-struct _lowcore { +- uint8_t pad_0x0000[0x0014-0x0000]; /* 0x0000 */ +- uint32_t ipl_parmblock_ptr; /* 0x0014 */ +- uint8_t pad_0x0018[0x0080-0x0018]; /* 0x0018 */ +- uint32_t ext_params; /* 0x0080 */ +- uint16_t ext_cpu_addr; /* 0x0084 */ +- uint16_t ext_int_code; /* 0x0086 */ +- uint16_t svc_ilc; /* 0x0088 */ +- uint16_t svc_code; /* 0x008a */ +- uint16_t pgm_ilc; /* 0x008c */ +- uint16_t pgm_code; /* 0x008e */ +- uint32_t data_exc_code; /* 0x0090 */ +- uint16_t mon_class_num; /* 0x0094 */ +- uint16_t per_perc_atmid; /* 0x0096 */ +- uint64_t per_address; /* 0x0098 */ +- uint8_t exc_access_id; /* 0x00a0 */ +- uint8_t per_access_id; /* 0x00a1 */ +- uint8_t op_access_id; /* 0x00a2 */ +- uint8_t ar_access_id; /* 0x00a3 */ +- uint8_t pad_0x00a4[0x00a8-0x00a4]; /* 0x00a4 */ +- uint64_t trans_exc_code; /* 0x00a8 */ +- uint64_t monitor_code; /* 0x00b0 */ +- uint16_t subchannel_id; /* 0x00b8 */ +- uint16_t subchannel_nr; /* 0x00ba */ +- uint32_t io_int_parm; /* 0x00bc */ +- uint32_t io_int_word; /* 0x00c0 */ +- uint8_t pad_0x00c4[0x00c8-0x00c4]; /* 0x00c4 */ +- uint32_t stfl_fac_list; /* 0x00c8 */ +- uint8_t pad_0x00cc[0x00e8-0x00cc]; /* 0x00cc */ +- uint32_t mcck_interruption_code[2]; /* 0x00e8 */ +- uint8_t pad_0x00f0[0x00f4-0x00f0]; /* 0x00f0 */ +- uint32_t external_damage_code; /* 0x00f4 */ +- uint64_t failing_storage_address; /* 0x00f8 */ +- uint8_t pad_0x0100[0x0110-0x0100]; /* 0x0100 */ +- uint64_t breaking_event_addr; /* 0x0110 */ +- uint8_t pad_0x0118[0x0120-0x0118]; /* 0x0118 */ +- struct psw_t restart_old_psw; /* 0x0120 */ +- struct psw_t external_old_psw; /* 0x0130 */ +- struct psw_t svc_old_psw; /* 0x0140 */ +- struct psw_t program_old_psw; /* 0x0150 */ +- struct psw_t mcck_old_psw; /* 0x0160 */ +- struct psw_t io_old_psw; /* 0x0170 */ +- uint8_t pad_0x0180[0x01a0-0x0180]; /* 0x0180 */ +- struct psw_t restart_psw; /* 0x01a0 */ +- struct psw_t external_new_psw; /* 0x01b0 */ +- struct psw_t svc_new_psw; /* 0x01c0 */ +- struct psw_t program_new_psw; /* 0x01d0 */ +- struct psw_t mcck_new_psw; /* 0x01e0 */ +- struct psw_t io_new_psw; /* 0x01f0 */ +- +- /* Save areas. */ +- uint64_t save_area_sync[8]; /* 0x0200 */ +- uint64_t save_area_async[8]; /* 0x0240 */ +- uint64_t save_area_restart[1]; /* 0x0280 */ +- uint8_t pad_0x0288[0x0290-0x0288]; /* 0x0288 */ +- +- /* Return psws. */ +- struct psw_t return_psw; /* 0x0290 */ +- struct psw_t return_mcck_psw; /* 0x02a0 */ +- +- /* CPU accounting and timing values. */ +- uint64_t sync_enter_timer; /* 0x02b0 */ +- uint64_t async_enter_timer; /* 0x02b8 */ +- uint64_t mcck_enter_timer; /* 0x02c0 */ +- uint64_t exit_timer; /* 0x02c8 */ +- uint64_t user_timer; /* 0x02d0 */ +- uint64_t system_timer; /* 0x02d8 */ +- uint64_t steal_timer; /* 0x02e0 */ +- uint64_t last_update_timer; /* 0x02e8 */ +- uint64_t last_update_clock; /* 0x02f0 */ +- uint64_t int_clock; /* 0x02f8 */ +- uint64_t mcck_clock; /* 0x0300 */ +- uint64_t clock_comparator; /* 0x0308 */ +- +- /* Current process. */ +- uint64_t current_task; /* 0x0310 */ +- uint64_t thread_info; /* 0x0318 */ +- uint64_t kernel_stack; /* 0x0320 */ +- +- /* Interrupt, panic and restart stack. */ +- uint64_t async_stack; /* 0x0328 */ +- uint64_t panic_stack; /* 0x0330 */ +- uint64_t restart_stack; /* 0x0338 */ +- +- /* Restart function and parameter. */ +- uint64_t restart_fn; /* 0x0340 */ +- uint64_t restart_data; /* 0x0348 */ +- uint64_t restart_source; /* 0x0350 */ +- +- /* Address space pointer. */ +- uint64_t kernel_asce; /* 0x0358 */ +- uint64_t user_asce; /* 0x0360 */ +- uint64_t current_pid; /* 0x0368 */ +- +- /* SMP info area */ +- uint32_t cpu_nr; /* 0x0370 */ +- uint32_t softirq_pending; /* 0x0374 */ +- uint64_t percpu_offset; /* 0x0378 */ +- uint64_t vdso_per_cpu_data; /* 0x0380 */ +- uint64_t machine_flags; /* 0x0388 */ +- uint64_t ftrace_func; /* 0x0390 */ +- uint64_t gmap; /* 0x0398 */ +- uint8_t pad_0x03a0[0x0400-0x03a0]; /* 0x03a0 */ +- +- /* Interrupt response block. */ +- uint8_t irb[64]; /* 0x0400 */ +- +- /* Per cpu primary space access list */ +- uint32_t paste[16]; /* 0x0440 */ +- +- uint8_t pad_0x0480[0x0e00-0x0480]; /* 0x0480 */ +- +- /* +- * 0xe00 contains the address of the IPL Parameter Information +- * block. Dump tools need IPIB for IPL after dump. +- * Note: do not change the position of any fields in 0x0e00-0x0f00 +- */ +- uint64_t ipib; /* 0x0e00 */ +- uint32_t ipib_checksum; /* 0x0e08 */ +- uint64_t vmcore_info; /* 0x0e0c */ +- uint8_t pad_0x0e14[0x0e18-0x0e14]; /* 0x0e14 */ +- uint64_t os_info; /* 0x0e18 */ +- uint8_t pad_0x0e20[0x0f00-0x0e20]; /* 0x0e20 */ +- +- /* Extended facility list */ +- uint64_t stfle_fac_list[32]; /* 0x0f00 */ +- uint8_t pad_0x1000[0x11b0-0x1000]; /* 0x1000 */ +- uint64_t vector_save_area_addr; /* 0x11b0 */ +- /* 64 bit extparam used for pfault/diag 250: defined by architecture */ +- uint64_t ext_params2; /* 0x11B8 */ +- uint8_t pad_0x11c0[0x1200-0x11C0]; /* 0x11C0 */ +- +- /* CPU register save area: defined by architecture */ +- uint64_t floating_pt_save_area[16]; /* 0x1200 */ +- uint64_t gpregs_save_area[16]; /* 0x1280 */ +- struct psw_t psw_save_area; /* 0x1300 */ +- uint8_t pad_0x1310[0x1318-0x1310]; /* 0x1310 */ +- uint32_t prefixreg_save_area; /* 0x1318 */ +- uint32_t fpt_creg_save_area; /* 0x131c */ +- uint8_t pad_0x1320[0x1324-0x1320]; /* 0x1320 */ +- uint32_t tod_progreg_save_area; /* 0x1324 */ +- uint32_t cpu_timer_save_area[2]; /* 0x1328 */ +- uint32_t clock_comp_save_area[2]; /* 0x1330 */ +- uint8_t pad_0x1338[0x1340-0x1338]; /* 0x1338 */ +- uint32_t access_regs_save_area[16]; /* 0x1340 */ +- uint64_t cregs_save_area[16]; /* 0x1380 */ +- uint8_t pad_0x1400[0x1800-0x1400]; /* 0x1400 */ +- +- /* Transaction abort diagnostic block */ +- uint8_t pgm_tdb[256]; /* 0x1800 */ +- +- /* align to the top of the prefix area */ +- uint8_t pad_0x1900[0x2000-0x1900]; /* 0x1900 */ +-} __packed __aligned(8192); +- +-#define S390_lowcore (*((struct _lowcore *) 0)) +- +-#define __LC_IPLDEV 0x0c6c +-#define __LC_OS_INFO 0x0e18 +- +-#define PAGE_SIZE 4096 +- +-void panic_notify(unsigned long reason); +- +-#define panic(reason, x...) \ +-do { \ +- printf(x); \ +- panic_notify(reason); \ +- libc_stop(reason); \ +-} while (0) +- +-static __always_inline int page_is_valid(unsigned long addr) +-{ +- unsigned long tmp; +- int rc; +- +- asm volatile( +- "0: ic %1,%2\n" +- "1: lhi %0,1\n" +- "2:\n" +- ".pushsection .fixup, \"ax\"\n" +- "3: xr %0,%0\n" +- " jg 2b\n" +- ".popsection\n" +- EX_TABLE(0b, 3b) EX_TABLE(1b, 3b) +- : "=d" (rc), "=d" (tmp) +- : "Q" (*(unsigned long *) addr) +- : "cc"); +- return rc; +-} +- +-static __always_inline uint32_t csum_partial(const void *buf, int len, uint32_t sum) +-{ +- register unsigned long reg2 asm("2") = (unsigned long) buf; +- register unsigned long reg3 asm("3") = (unsigned long) len; +- +- asm volatile( +- "0: cksm %0,%1\n" /* do checksum on longs */ +- " jo 0b\n" +- : "+d" (sum), "+d" (reg2), "+d" (reg3) : : "cc", "memory"); +- return sum; +-} +- +-#define __ctl_store(array, low, high) ({ \ +- typedef struct { char _[sizeof(array)]; } __may_alias addrtype;\ +- asm volatile( \ +- " stctg %1,%2,%0\n" \ +- : "=Q" (*(addrtype *)(&array)) \ +- : "i" (low), "i" (high)); \ +-}) +- +-#define __ctl_load(array, low, high) ({ \ +- typedef struct { char _[sizeof(array)]; } __may_alias addrtype; \ +- asm volatile( \ +- " lctlg %1,%2,%0\n" \ +- : : "Q" (*(addrtype *)(&array)), \ +- "i" (low), "i" (high)); \ +-}) +- +-static __always_inline void __ctl_set_bit(unsigned int cr, unsigned int bit) +-{ +- unsigned long reg; +- +- __ctl_store(reg, cr, cr); +- reg |= 1UL << bit; +- __ctl_load(reg, cr, cr); +-} +- +-/* +- * DIAG 308 support +- */ +-enum diag308_subcode { +- DIAG308_REL_HSA = 2, +- DIAG308_IPL = 3, +- DIAG308_DUMP = 4, +- DIAG308_SET = 5, +- DIAG308_STORE = 6, +-}; +- +-static __always_inline int diag308(unsigned long subcode, void *addr) +-{ +- register unsigned long _addr asm("0") = (unsigned long) addr; +- register unsigned long _rc asm("1") = 0; +- +- asm volatile( +- " diag %0,%2,0x308\n" +- "0:\n" +- : "+d" (_addr), "+d" (_rc) +- : "d" (subcode) : "cc", "memory"); +- return _rc; +-} +- +-/* +- * Store CPU address +- */ +-static __always_inline unsigned short stap(void) +-{ +- unsigned short cpu_address; +- +- asm volatile("stap %0" : "=m" (cpu_address)); +- return cpu_address; +-} +- +-/* +- * Program the clock comparator +- */ +-static __always_inline void set_clock_comparator(uint64_t time) +-{ +- asm volatile("sckc %0" : : "Q" (time)); +-} +- +-/* +- * Program the CPU timer +- */ +-static __always_inline void set_cpu_timer(uint64_t timer) +-{ +- asm volatile("spt %0" : : "Q" (timer)); +-} +- +-/* +- * Get current time (store clock) +- */ +-static __always_inline unsigned long long get_tod_clock(void) +-{ +- unsigned long long clk; +- +- asm volatile("stck %0" : "=Q" (clk) : : "cc"); +- return clk; +-} +- +-/* +- * Get ID of current CPU +- */ +-struct cpuid { +- unsigned int version:8; +- unsigned int ident:24; +- unsigned int machine:16; +- unsigned int unused:16; +-} __packed __aligned(8); +- +-static __always_inline void get_cpu_id(struct cpuid *ptr) +-{ +- asm volatile("stidp %0" : "=Q" (*ptr)); +-} +- +-/* +- * Check if we run under z/VM +- */ +-static __always_inline int is_zvm(void) +-{ +- struct cpuid cpuid; +- +- get_cpu_id(&cpuid); +- return cpuid.version == 0xff; +-} +- +-/* +- * Vector register definition +- */ +-typedef struct { +- uint32_t u[4]; +-} __vector128; +- +-/* +- * Save vector registers +- */ +-static __always_inline void save_vx_regs(__vector128 *vxrs) +-{ +- typedef struct { __vector128 _[32]; } addrtype; +- +- asm volatile( +- " la 1,%0\n" +- " .word 0xe70f,0x1000,0x003e\n" /* vstm 0,15,0(1) */ +- " .word 0xe70f,0x1100,0x0c3e\n" /* vstm 16,31,256(1) */ +- : "=Q" (*(addrtype *) vxrs) : : "1"); +-} +- +-/* +- * Save vector registers safe +- */ +-static __always_inline void save_vx_regs_safe(__vector128 *vxrs) +-{ +- unsigned long cr0; +- +- __ctl_store(cr0, 0, 0); +- __ctl_set_bit(0, 17); +- __ctl_set_bit(0, 18); /* AFP-register-control */ +- save_vx_regs(vxrs); +- __ctl_load(cr0, 0, 0); +-} +- +-#define MAX_FACILITY_BIT (256*8) /* stfle_fac_list has 256 bytes */ +- +-static __always_inline int __test_facility(unsigned long nr, void *facilities) +-{ +- unsigned char *ptr; +- +- if (nr >= MAX_FACILITY_BIT) +- return 0; +- ptr = (unsigned char *) facilities + (nr >> 3); +- return (*ptr & (0x80 >> (nr & 7))) != 0; +-} +- +-/* +- * The test_facility function uses the bit odering where the MSB is bit 0. +- * That makes it easier to query facility bits with the bit number as +- * documented in the Principles of Operation. +- */ +-static __always_inline int test_facility(unsigned long nr) +-{ +- return __test_facility(nr, &S390_lowcore.stfle_fac_list); +-} +- +-static __always_inline unsigned long __stfle_asm(uint64_t *stfle_fac_list, int size) +-{ +- register unsigned long reg0 asm("0") = size - 1; +- +- asm volatile( +- ".insn s,0xb2b00000,0(%1)" /* stfle */ +- : "+d" (reg0) +- : "a" (stfle_fac_list) +- : "memory", "cc"); +- return reg0; +-} +- +-/** +- * stfle - Store facility list extended +- * @stfle_fac_list: array where facility list can be stored +- * @size: size of passed in array in double words +- */ +-static __always_inline void stfle(uint64_t *stfle_fac_list, int size) +-{ +- unsigned long nr; +- +- asm volatile( +- " .insn s,0xb2b10000,0(0)\n" /* stfl */ +- "0:\n" +- EX_TABLE(0b, 0b) +- : "+m" (S390_lowcore.stfl_fac_list)); +- nr = 4; /* bytes stored by stfl */ +- memcpy(stfle_fac_list, &S390_lowcore.stfl_fac_list, 4); +- if (S390_lowcore.stfl_fac_list & 0x01000000) { +- /* More facility bits available with stfle */ +- nr = __stfle_asm(stfle_fac_list, size); +- nr = MIN((nr + 1) * 8, size * 8UL); +- } +- memset((char *) stfle_fac_list + nr, 0, size * 8 - nr); +-} +- +-#endif /* S390_H */ +--- a/zipl/boot/sclp.c ++++ b/zipl/boot/sclp.c +@@ -11,7 +11,7 @@ + + #include "libc.h" + #include "error.h" +-#include "s390.h" ++#include "boot/s390.h" + #include "sclp.h" + + /* Perform service call. Return 0 on success, non-zero otherwise. */ +--- a/zipl/boot/sclp.h ++++ b/zipl/boot/sclp.h +@@ -13,7 +13,7 @@ + #define SCLP_H + + #include "libc.h" +-#include "s390.h" ++#include "boot/s390.h" + + /* vector keys and ids */ + #define GDS_ID_MDSMU 0x1310 +--- a/zipl/boot/stage2.c ++++ b/zipl/boot/stage2.c +@@ -14,7 +14,7 @@ + #include "error.h" + #include "libc.h" + #include "menu.h" +-#include "s390.h" ++#include "boot/s390.h" + #include "stage2.h" + + static int is_null_descriptor(disk_blockptr_t *address) +--- a/zipl/boot/stage2.h ++++ b/zipl/boot/stage2.h +@@ -15,7 +15,7 @@ + #include "cio.h" + #include "error.h" + #include "libc.h" +-#include "s390.h" ++#include "boot/s390.h" + + #define DESCR_PER_BLOCK 16 + +@@ -76,4 +76,3 @@ void kdump_stage2(unsigned long); + + + #endif /* COMMON_H */ +- +--- a/zipl/boot/stage2dump.h ++++ b/zipl/boot/stage2dump.h +@@ -13,7 +13,7 @@ + #define STAGE2DUMP_H + + #include "libc.h" +-#include "s390.h" ++#include "boot/s390.h" + + #define IPL_SC *((struct subchannel_id *) &S390_lowcore.subchannel_id) + #define ROUND_DOWN(x, a) ((x) & ~((typeof(x))(a) - 1)) +--- a/zipl/boot/stage3.c ++++ b/zipl/boot/stage3.c +@@ -11,7 +11,7 @@ + + #include "libc.h" + #include "boot/sigp.h" +-#include "s390.h" ++#include "boot/s390.h" + #include "stage3.h" + #include "error.h" + #include "zipl.h" +--- a/zipl/boot/stage3.h ++++ b/zipl/boot/stage3.h +@@ -13,8 +13,8 @@ + #define STAGE3_H + + #include "libc.h" +-#include "s390.h" + ++#include "boot/s390.h" + #include "boot/ipl.h" + #include "boot/linux_layout.h" + diff --git a/s390-tools-sles15sp2-35-zipl-libc-include-s390.h.patch b/s390-tools-sles15sp2-35-zipl-libc-include-s390.h.patch new file mode 100644 index 0000000..9789bcd --- /dev/null +++ b/s390-tools-sles15sp2-35-zipl-libc-include-s390.h.patch @@ -0,0 +1,51 @@ +Subject: [PATCH] [FEAT VS1804] zipl/libc: include 's390.h' +From: Marc Hartmayer + +Summary: genprotimg: Introduce new tool for the creation of PV images +Description: genprotimg takes a kernel, host-key documents, optionally an + initrd, optionally a file with the kernel command line, and it + generates a single, loadable image file. The image consists of a + concatenation of a plain text boot loader, the encrypted + components for kernel, initrd, and cmdline, and the + integrity-protected PV header, containing metadata necessary for + running the guest in PV mode. It's possible to use this image file + as a kernel for zIPL or for a direct kernel boot using QEMU. +Upstream-ID: b0f82d22f9f60a0a8db1976751aa5a875e7c5f80 +Problem-ID: VS1804 + +Upstream-Description: + + zipl/libc: include 's390.h' + + Include 'boot/s390.h' in 'libc.c' as `PAGE_SIZE` is used there and + move the 'libc.h' include directive to the top. + + Reviewed-by: Philipp Rudo + Reviewed-by: Stefan Haberland + Signed-off-by: Marc Hartmayer + Signed-off-by: Jan Höppner + + +Signed-off-by: Marc Hartmayer +--- + zipl/boot/libc.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/zipl/boot/libc.c ++++ b/zipl/boot/libc.c +@@ -9,12 +9,14 @@ + * it under the terms of the MIT license. See LICENSE for details. + */ + ++#include "libc.h" ++ + #include + + #include "lib/zt_common.h" ++#include "boot/s390.h" + + #include "error.h" +-#include "libc.h" + #include "sclp.h" + + extern char __heap_start[]; diff --git a/s390-tools-sles15sp2-36-include-boot-s390.h-move-panic-and-panic_notify-to-l.patch b/s390-tools-sles15sp2-36-include-boot-s390.h-move-panic-and-panic_notify-to-l.patch new file mode 100644 index 0000000..bb13ac3 --- /dev/null +++ b/s390-tools-sles15sp2-36-include-boot-s390.h-move-panic-and-panic_notify-to-l.patch @@ -0,0 +1,69 @@ +Subject: [PATCH] [FEAT VS1804] include/boot/s390.h: move panic and panic_notify to libc.h +From: Marc Hartmayer + +Summary: genprotimg: Introduce new tool for the creation of PV images +Description: genprotimg takes a kernel, host-key documents, optionally an + initrd, optionally a file with the kernel command line, and it + generates a single, loadable image file. The image consists of a + concatenation of a plain text boot loader, the encrypted + components for kernel, initrd, and cmdline, and the + integrity-protected PV header, containing metadata necessary for + running the guest in PV mode. It's possible to use this image file + as a kernel for zIPL or for a direct kernel boot using QEMU. +Upstream-ID: 2568863f581cff9bf3b1e27c2d2917b5ae3b5177 +Problem-ID: VS1804 + +Upstream-Description: + + include/boot/s390.h: move panic and panic_notify to libc.h + + ... as this code is not s390 specific and not every user of s390.h + wants to implement `panic_notify`. + + Reviewed-by: Philipp Rudo + Reviewed-by: Stefan Haberland + Signed-off-by: Marc Hartmayer + Signed-off-by: Jan Höppner + + +Signed-off-by: Marc Hartmayer +--- + include/boot/s390.h | 9 --------- + zipl/boot/libc.h | 8 ++++++++ + 2 files changed, 8 insertions(+), 9 deletions(-) + +--- a/include/boot/s390.h ++++ b/include/boot/s390.h +@@ -201,15 +201,6 @@ struct _lowcore { + #define S390_lowcore (*((struct _lowcore *) 0)) + + +-void panic_notify(unsigned long reason); +- +-#define panic(reason, x...) \ +-do { \ +- printf(x); \ +- panic_notify(reason); \ +- libc_stop(reason); \ +-} while (0) +- + static __always_inline int page_is_valid(unsigned long addr) + { + unsigned long tmp; +--- a/zipl/boot/libc.h ++++ b/zipl/boot/libc.h +@@ -61,6 +61,14 @@ void libc_stop(unsigned long); + void start(void); + void pgm_check_handler(void); + void pgm_check_handler_fn(void); ++void panic_notify(unsigned long reason); ++ ++#define panic(reason, ...) \ ++ do { \ ++ printf(__VA_ARGS__); \ ++ panic_notify(reason); \ ++ libc_stop(reason); \ ++ } while (0) + + static inline int isdigit(int c) + { diff --git a/s390-tools-sles15sp2-37-include-boot-s390.h-fixes-for-Werror-sign-conversion.patch b/s390-tools-sles15sp2-37-include-boot-s390.h-fixes-for-Werror-sign-conversion.patch new file mode 100644 index 0000000..e781b65 --- /dev/null +++ b/s390-tools-sles15sp2-37-include-boot-s390.h-fixes-for-Werror-sign-conversion.patch @@ -0,0 +1,73 @@ +Subject: [PATCH] [FEAT VS1804] include/boot/s390.h: fixes for -Werror=sign-conversion +From: Marc Hartmayer + +Summary: genprotimg: Introduce new tool for the creation of PV images +Description: genprotimg takes a kernel, host-key documents, optionally an + initrd, optionally a file with the kernel command line, and it + generates a single, loadable image file. The image consists of a + concatenation of a plain text boot loader, the encrypted + components for kernel, initrd, and cmdline, and the + integrity-protected PV header, containing metadata necessary for + running the guest in PV mode. It's possible to use this image file + as a kernel for zIPL or for a direct kernel boot using QEMU. +Upstream-ID: 305235a7bce814f71ec113a612b6117c96894e23 +Problem-ID: VS1804 + +Upstream-Description: + + include/boot/s390.h: fixes for -Werror=sign-conversion + + Errors fixed: + + ../../include/boot/s390.h: In function '__stfle_asm': + ../../include/boot/s390.h:424:41: error: conversion to 'long unsigned int' from 'int' may change the sign of the result [-Werror=sign-conversion] + register unsigned long reg0 asm("0") = size - 1; + + ../../include/boot/s390.h: In function 'stfle': + ../../include/boot/s390.h:453:31: error: conversion to 'long unsigned int' from 'int' may change the sign of the result [-Werror=sign-conversion] + nr = MIN((nr + 1) * 8, size * 8UL); + + ../../include/boot/s390.h: In function 'diag308': + ../../include/boot/s390.h:296:9: error: conversion from 'long unsigned int' to 'int' may change value [-Werror=conversion] + return _rc; + + Reviewed-by: Philipp Rudo + Reviewed-by: Stefan Haberland + Signed-off-by: Marc Hartmayer + Signed-off-by: Jan Höppner + + +Signed-off-by: Marc Hartmayer +--- + include/boot/s390.h | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/include/boot/s390.h ++++ b/include/boot/s390.h +@@ -269,7 +269,7 @@ enum diag308_subcode { + DIAG308_STORE = 6, + }; + +-static __always_inline int diag308(unsigned long subcode, void *addr) ++static __always_inline unsigned long diag308(unsigned long subcode, void *addr) + { + register unsigned long _addr asm("0") = (unsigned long) addr; + register unsigned long _rc asm("1") = 0; +@@ -403,7 +403,7 @@ static __always_inline int test_facility + return __test_facility(nr, &S390_lowcore.stfle_fac_list); + } + +-static __always_inline unsigned long __stfle_asm(uint64_t *stfle_fac_list, int size) ++static __always_inline unsigned long __stfle_asm(uint64_t *stfle_fac_list, unsigned int size) + { + register unsigned long reg0 asm("0") = size - 1; + +@@ -420,7 +420,7 @@ static __always_inline unsigned long __s + * @stfle_fac_list: array where facility list can be stored + * @size: size of passed in array in double words + */ +-static __always_inline void stfle(uint64_t *stfle_fac_list, int size) ++static __always_inline void stfle(uint64_t *stfle_fac_list, unsigned int size) + { + unsigned long nr; + diff --git a/s390-tools-sles15sp2-38-zipl-refactor-all-EBCDIC-code-into-separate-files.patch b/s390-tools-sles15sp2-38-zipl-refactor-all-EBCDIC-code-into-separate-files.patch new file mode 100644 index 0000000..0662a64 --- /dev/null +++ b/s390-tools-sles15sp2-38-zipl-refactor-all-EBCDIC-code-into-separate-files.patch @@ -0,0 +1,640 @@ +Subject: [PATCH] [FEAT VS1804] zipl: refactor all EBCDIC code into separate files +From: Marc Hartmayer + +Summary: genprotimg: Introduce new tool for the creation of PV images +Description: genprotimg takes a kernel, host-key documents, optionally an + initrd, optionally a file with the kernel command line, and it + generates a single, loadable image file. The image consists of a + concatenation of a plain text boot loader, the encrypted + components for kernel, initrd, and cmdline, and the + integrity-protected PV header, containing metadata necessary for + running the guest in PV mode. It's possible to use this image file + as a kernel for zIPL or for a direct kernel boot using QEMU. +Upstream-ID: a37170b8bec07a0ffc3270a4c78124e1117f0337 +Problem-ID: VS1804 + +Upstream-Description: + + zipl: refactor all EBCDIC code into separate files + + This allows the reuse of the code later in sclp.c. While at it, also + declare @source parameter of `ebcdic_to_ascii` function as `const` and + rename all `ebc_` function name prefixes into `ebcdic_`. Move + conversion tables to separate file so it only gets linked into loaders + that need it. + + Reviewed-by: Philipp Rudo + Reviewed-by: Stefan Haberland + Signed-off-by: Marc Hartmayer + Signed-off-by: Jan Höppner + + +Signed-off-by: Marc Hartmayer +--- + zipl/boot/Makefile | 16 ++-- + zipl/boot/ebcdic.c | 30 ++++++++ + zipl/boot/ebcdic.h | 45 ++++++++++++ + zipl/boot/ebcdic_conv.c | 167 ++++++++++++++++++++++++++++++++++++++++++++++++ + zipl/boot/ebcdic_conv.h | 21 ++++++ + zipl/boot/libc.c | 19 ----- + zipl/boot/libc.h | 25 ------- + zipl/boot/menu.c | 9 +- + zipl/boot/stage3.c | 156 -------------------------------------------- + 9 files changed, 280 insertions(+), 208 deletions(-) + +--- a/zipl/boot/Makefile ++++ b/zipl/boot/Makefile +@@ -28,22 +28,22 @@ all: data.o data.h tape0.bin stage3.bin + + eckd2dump_sv.exec: \ + head.o stage2dump.o cio.o eckd2dump.o eckd2dump_sv.o \ +- libc.o sclp.o entry.o ++ libc.o ebcdic.o sclp.o entry.o + eckd2dump_mv.exec: \ + head.o stage2dump.o cio.o eckd2dump.o eckd2dump_mv.o \ +- libc.o sclp.o entry.o ++ libc.o ebcdic.o sclp.o entry.o + fba2dump.exec: \ + head.o stage2dump.o cio.o fba2dump.o \ +- libc.o sclp.o entry.o ++ libc.o ebcdic.o sclp.o entry.o + tape2dump.exec: \ + head.o stage2dump.o cio.o tape2dump.o \ +- libc.o sclp.o entry.o +-eckd2.exec: head.o stage2.o cio.o eckd2.o libc.o menu.o sclp.o \ ++ libc.o ebcdic.o sclp.o entry.o ++eckd2.exec: head.o stage2.o cio.o eckd2.o libc.o ebcdic.o menu.o sclp.o \ + kdump2.o kdump.o entry.o +-fba2.exec: head.o stage2.o cio.o fba2.o libc.o menu.o sclp.o \ ++fba2.exec: head.o stage2.o cio.o fba2.o libc.o ebcdic.o menu.o sclp.o \ + kdump2.o kdump.o entry.o +-stage3.exec: head.o stage3.o kdump3.o libc.o sclp.o sclp_stage3.o \ +- kdump.o entry.o stage3.lds ++stage3.exec: head.o stage3.o kdump3.o libc.o ebcdic.o ebcdic_conv.o sclp.o \ ++ sclp_stage3.o kdump.o entry.o stage3.lds + + %.exec: %.o + STAGE=$$( \ +--- /dev/null ++++ b/zipl/boot/ebcdic.c +@@ -0,0 +1,30 @@ ++/* ++ * EBCDIC specific functions ++ * ++ * Copyright IBM Corp. 2013, 2020 ++ * ++ * s390-tools is free software; you can redistribute it and/or modify ++ * it under the terms of the MIT license. See LICENSE for details. ++ * ++ */ ++ ++#include "ebcdic.h" ++ ++ ++/* ++ * Convert ebcdic string to number with given base ++ */ ++unsigned long ebcdic_strtoul(char *nptr, char **endptr, int base) ++{ ++ unsigned long val = 0; ++ ++ while (ebcdic_isdigit(*nptr)) { ++ if (val != 0) ++ val *= base; ++ val += *nptr - 0xf0; ++ nptr++; ++ } ++ if (endptr) ++ *endptr = (char *)nptr; ++ return val; ++} +--- /dev/null ++++ b/zipl/boot/ebcdic.h +@@ -0,0 +1,45 @@ ++/* ++ * EBCDIC specific functions ++ * ++ * Copyright IBM Corp. 2013, 2020 ++ * ++ * s390-tools is free software; you can redistribute it and/or modify ++ * it under the terms of the MIT license. See LICENSE for details. ++ * ++ */ ++ ++#ifndef EBCDIC_H ++#define EBCDIC_H ++ ++#include "lib/zt_common.h" ++ ++ ++#ifndef __ASSEMBLER__ ++ ++unsigned long ebcdic_strtoul(char *, char **, int); ++ ++static __always_inline int ecbdic_isspace(char c) ++{ ++ return (c == 0x40) || (c == 0x05) || (c == 0x15) || (c == 0x25) || ++ (c == 0x0b) || (c == 0x0c) || (c == 0x0d); ++} ++ ++static __always_inline int ebcdic_isdigit(char c) ++{ ++ return (c >= 0xf0) && (c <= 0xf9); ++} ++ ++static __always_inline int ebcdic_isupper(char c) ++{ ++ return (c >= 0xC1 && c <= 0xC9) || (c >= 0xD1 && c <= 0xD9) || ++ (c >= 0xE2 && c <= 0xE9); ++} ++ ++static __always_inline char ebcdic_tolower(char c) ++{ ++ if (ebcdic_isupper(c)) ++ c -= 0x40; ++ return c; ++} ++#endif /* __ASSEMBLER__ */ ++#endif /* EBCDIC_H */ +--- /dev/null ++++ b/zipl/boot/ebcdic_conv.c +@@ -0,0 +1,167 @@ ++/* ++ * EBCDIC conversion functions ++ * ++ * Copyright IBM Corp. 2013, 2020 ++ * ++ * s390-tools is free software; you can redistribute it and/or modify ++ * it under the terms of the MIT license. See LICENSE for details. ++ * ++ */ ++ ++#include "ebcdic_conv.h" ++#include "libc.h" ++#include "boot/s390.h" ++ ++ ++static unsigned char ebcdic_037[256] = { ++/* 0x00 NUL SOH STX ETX *SEL HT *RNL DEL */ ++ 0x00, 0x01, 0x02, 0x03, 0x07, 0x09, 0x07, 0x7F, ++/* 0x08 -GE -SPS -RPT VT FF CR SO SI */ ++ 0x07, 0x07, 0x07, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, ++/* 0x10 DLE DC1 DC2 DC3 -RES -NL BS -POC ++ -ENP ->LF */ ++ 0x10, 0x11, 0x12, 0x13, 0x07, 0x0A, 0x08, 0x07, ++/* 0x18 CAN EM -UBS -CU1 -IFS -IGS -IRS -ITB ++ -IUS */ ++ 0x18, 0x19, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, ++/* 0x20 -DS -SOS FS -WUS -BYP LF ETB ESC ++ -INP */ ++ 0x07, 0x07, 0x1C, 0x07, 0x07, 0x0A, 0x17, 0x1B, ++/* 0x28 -SA -SFE -SM -CSP -MFA ENQ ACK BEL ++ -SW */ ++ 0x07, 0x07, 0x07, 0x07, 0x07, 0x05, 0x06, 0x07, ++/* 0x30 ---- ---- SYN -IR -PP -TRN -NBS EOT */ ++ 0x07, 0x07, 0x16, 0x07, 0x07, 0x07, 0x07, 0x04, ++/* 0x38 -SBS -IT -RFF -CU3 DC4 NAK ---- SUB */ ++ 0x07, 0x07, 0x07, 0x07, 0x14, 0x15, 0x07, 0x1A, ++/* 0x40 SP RSP ä ---- */ ++ 0x20, 0xFF, 0x83, 0x84, 0x85, 0xA0, 0x07, 0x86, ++/* 0x48 . < ( + | */ ++ 0x87, 0xA4, 0x9B, 0x2E, 0x3C, 0x28, 0x2B, 0x7C, ++/* 0x50 & ---- */ ++ 0x26, 0x82, 0x88, 0x89, 0x8A, 0xA1, 0x8C, 0x07, ++/* 0x58 ß ! $ * ) ; */ ++ 0x8D, 0xE1, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0xAA, ++/* 0x60 - / ---- Ä ---- ---- ---- */ ++ 0x2D, 0x2F, 0x07, 0x8E, 0x07, 0x07, 0x07, 0x8F, ++/* 0x68 ---- , % _ > ? */ ++ 0x80, 0xA5, 0x07, 0x2C, 0x25, 0x5F, 0x3E, 0x3F, ++/* 0x70 --- ---- ---- ---- ---- ---- ---- */ ++ 0x07, 0x90, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, ++/* 0x78 * ` : # @ ' = " */ ++ 0x70, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22, ++/* 0x80 * a b c d e f g */ ++ 0x07, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, ++/* 0x88 h i ---- ---- ---- */ ++ 0x68, 0x69, 0xAE, 0xAF, 0x07, 0x07, 0x07, 0xF1, ++/* 0x90 ° j k l m n o p */ ++ 0xF8, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, ++/* 0x98 q r ---- ---- */ ++ 0x71, 0x72, 0xA6, 0xA7, 0x91, 0x07, 0x92, 0x07, ++/* 0xA0 ~ s t u v w x */ ++ 0xE6, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, ++/* 0xA8 y z ---- ---- ---- ---- */ ++ 0x79, 0x7A, 0xAD, 0xAB, 0x07, 0x07, 0x07, 0x07, ++/* 0xB0 ^ ---- § ---- */ ++ 0x5E, 0x9C, 0x9D, 0xFA, 0x07, 0x07, 0x07, 0xAC, ++/* 0xB8 ---- [ ] ---- ---- ---- ---- */ ++ 0xAB, 0x07, 0x5B, 0x5D, 0x07, 0x07, 0x07, 0x07, ++/* 0xC0 { A B C D E F G */ ++ 0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, ++/* 0xC8 H I ---- ö ---- */ ++ 0x48, 0x49, 0x07, 0x93, 0x94, 0x95, 0xA2, 0x07, ++/* 0xD0 } J K L M N O P */ ++ 0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, ++/* 0xD8 Q R ---- ü */ ++ 0x51, 0x52, 0x07, 0x96, 0x81, 0x97, 0xA3, 0x98, ++/* 0xE0 \ S T U V W X */ ++ 0x5C, 0xF6, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, ++/* 0xE8 Y Z ---- Ö ---- ---- ---- */ ++ 0x59, 0x5A, 0xFD, 0x07, 0x99, 0x07, 0x07, 0x07, ++/* 0xF0 0 1 2 3 4 5 6 7 */ ++ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, ++/* 0xF8 8 9 ---- ---- Ü ---- ---- ---- */ ++ 0x38, 0x39, 0x07, 0x07, 0x9A, 0x07, 0x07, 0x07 ++}; ++ ++static unsigned char ebcdic_500[256] = { ++/* 0x00 NUL SOH STX ETX *SEL HT *RNL DEL */ ++ 0x00, 0x01, 0x02, 0x03, 0x07, 0x09, 0x07, 0x7F, ++/* 0x08 -GE -SPS -RPT VT FF CR SO SI */ ++ 0x07, 0x07, 0x07, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, ++/* 0x10 DLE DC1 DC2 DC3 -RES -NL BS -POC ++ -ENP ->LF */ ++ 0x10, 0x11, 0x12, 0x13, 0x07, 0x0A, 0x08, 0x07, ++/* 0x18 CAN EM -UBS -CU1 -IFS -IGS -IRS -ITB ++ -IUS */ ++ 0x18, 0x19, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, ++/* 0x20 -DS -SOS FS -WUS -BYP LF ETB ESC ++ -INP */ ++ 0x07, 0x07, 0x1C, 0x07, 0x07, 0x0A, 0x17, 0x1B, ++/* 0x28 -SA -SFE -SM -CSP -MFA ENQ ACK BEL ++ -SW */ ++ 0x07, 0x07, 0x07, 0x07, 0x07, 0x05, 0x06, 0x07, ++/* 0x30 ---- ---- SYN -IR -PP -TRN -NBS EOT */ ++ 0x07, 0x07, 0x16, 0x07, 0x07, 0x07, 0x07, 0x04, ++/* 0x38 -SBS -IT -RFF -CU3 DC4 NAK ---- SUB */ ++ 0x07, 0x07, 0x07, 0x07, 0x14, 0x15, 0x07, 0x1A, ++/* 0x40 SP RSP ä ---- */ ++ 0x20, 0xFF, 0x83, 0x84, 0x85, 0xA0, 0x07, 0x86, ++/* 0x48 . < ( + | */ ++ 0x87, 0xA4, 0x9B, 0x2E, 0x3C, 0x28, 0x2B, 0x7C, ++/* 0x50 & ---- */ ++ 0x26, 0x82, 0x88, 0x89, 0x8A, 0xA1, 0x8C, 0x07, ++/* 0x58 ß ! $ * ) ; */ ++ 0x8D, 0xE1, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0xAA, ++/* 0x60 - / ---- Ä ---- ---- ---- */ ++ 0x2D, 0x2F, 0x07, 0x8E, 0x07, 0x07, 0x07, 0x8F, ++/* 0x68 ---- , % _ > ? */ ++ 0x80, 0xA5, 0x07, 0x2C, 0x25, 0x5F, 0x3E, 0x3F, ++/* 0x70 --- ---- ---- ---- ---- ---- ---- */ ++ 0x07, 0x90, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, ++/* 0x78 * ` : # @ ' = " */ ++ 0x70, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22, ++/* 0x80 * a b c d e f g */ ++ 0x07, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, ++/* 0x88 h i ---- ---- ---- */ ++ 0x68, 0x69, 0xAE, 0xAF, 0x07, 0x07, 0x07, 0xF1, ++/* 0x90 ° j k l m n o p */ ++ 0xF8, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, ++/* 0x98 q r ---- ---- */ ++ 0x71, 0x72, 0xA6, 0xA7, 0x91, 0x07, 0x92, 0x07, ++/* 0xA0 ~ s t u v w x */ ++ 0xE6, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, ++/* 0xA8 y z ---- ---- ---- ---- */ ++ 0x79, 0x7A, 0xAD, 0xAB, 0x07, 0x07, 0x07, 0x07, ++/* 0xB0 ^ ---- § ---- */ ++ 0x5E, 0x9C, 0x9D, 0xFA, 0x07, 0x07, 0x07, 0xAC, ++/* 0xB8 ---- [ ] ---- ---- ---- ---- */ ++ 0xAB, 0x07, 0x5B, 0x5D, 0x07, 0x07, 0x07, 0x07, ++/* 0xC0 { A B C D E F G */ ++ 0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, ++/* 0xC8 H I ---- ö ---- */ ++ 0x48, 0x49, 0x07, 0x93, 0x94, 0x95, 0xA2, 0x07, ++/* 0xD0 } J K L M N O P */ ++ 0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, ++/* 0xD8 Q R ---- ü */ ++ 0x51, 0x52, 0x07, 0x96, 0x81, 0x97, 0xA3, 0x98, ++/* 0xE0 \ S T U V W X */ ++ 0x5C, 0xF6, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, ++/* 0xE8 Y Z ---- Ö ---- ---- ---- */ ++ 0x59, 0x5A, 0xFD, 0x07, 0x99, 0x07, 0x07, 0x07, ++/* 0xF0 0 1 2 3 4 5 6 7 */ ++ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, ++/* 0xF8 8 9 ---- ---- Ü ---- ---- ---- */ ++ 0x38, 0x39, 0x07, 0x07, 0x9A, 0x07, 0x07, 0x07 ++}; ++ ++void ebcdic_to_ascii(unsigned char *target, const unsigned char *source, ++ unsigned int l) ++{ ++ unsigned char *ebc; ++ unsigned int i; ++ ++ ebc = is_zvm() ? ebcdic_037 : ebcdic_500; ++ for (i = 0; i < l; i++) ++ target[i] = ebc[source[i]]; ++} +--- /dev/null ++++ b/zipl/boot/ebcdic_conv.h +@@ -0,0 +1,21 @@ ++/* ++ * EBCDIC conversion functions ++ * ++ * Copyright IBM Corp. 2013, 2020 ++ * ++ * s390-tools is free software; you can redistribute it and/or modify ++ * it under the terms of the MIT license. See LICENSE for details. ++ * ++ */ ++ ++#ifndef EBCDIC_CONV_H ++#define EBCDIC_CONV_H ++ ++ ++#ifndef __ASSEMBLER__ ++ ++void ebcdic_to_ascii(unsigned char *target, const unsigned char *source, ++ unsigned int l); ++ ++#endif /* __ASSEMBLER__ */ ++#endif /* EBCDIC_CONV_H */ +--- a/zipl/boot/libc.c ++++ b/zipl/boot/libc.c +@@ -18,6 +18,7 @@ + + #include "error.h" + #include "sclp.h" ++#include "ebcdic.h" + + extern char __heap_start[]; + extern char __heap_stop[]; +@@ -129,24 +130,6 @@ int strncmp(const char *s1, const char * + return 0; + } + +-/* +- * Convert ebcdic string to number with given base +- */ +-unsigned long ebcstrtoul(char *nptr, char **endptr, int base) +-{ +- unsigned long val = 0; +- +- while (ebc_isdigit(*nptr)) { +- if (val != 0) +- val *= base; +- val += *nptr - 0xf0; +- nptr++; +- } +- if (endptr) +- *endptr = (char *) nptr; +- return val; +-} +- + static int skip_atoi(const char **c) + { + int i = 0; +--- a/zipl/boot/libc.h ++++ b/zipl/boot/libc.h +@@ -51,7 +51,6 @@ void *memmove(void *, const void *, unsi + void *memset(void *, int c, unsigned long); + char *strcat(char *, const char *); + int strncmp(const char *, const char *, unsigned long); +-unsigned long ebcstrtoul(char *, char **, int); + int strlen(const char *); + char *strcpy(char *, const char *); + unsigned long get_zeroed_page(void); +@@ -80,28 +79,4 @@ static inline int isspace(char c) + return (c == 32) || (c >= 9 && c <= 13); + } + +-static inline int ebc_isspace(char c) +-{ +- return (c == 0x40) || (c == 0x05) || (c == 0x15) || (c == 0x25) || +- (c == 0x0b) || (c == 0x0c) || (c == 0x0d); +-} +- +-static inline int ebc_isdigit(char c) +-{ +- return (c >= 0xf0) && (c <= 0xf9); +-} +- +-static inline int ebc_isupper(char c) +-{ +- return (c >= 0xC1 && c <= 0xC9) || (c >= 0xD1 && c <= 0xD9) || +- (c >= 0xE2 && c <= 0xE9); +-} +- +-static inline char ebc_tolower(char c) +-{ +- if (ebc_isupper(c)) +- c -= 0x40; +- return c; +-} +- + #endif /* LIBC_H */ +--- a/zipl/boot/menu.c ++++ b/zipl/boot/menu.c +@@ -12,6 +12,7 @@ + #include "libc.h" + #include "menu.h" + #include "sclp.h" ++#include "ebcdic.h" + + static const char *msg_econfig = "Error: undefined configuration\n"; + +@@ -55,8 +56,8 @@ static int menu_read(void) + /* input under zVM needs to be converted to lower case */ + if (is_zvm()) + for (i = 0; i < count; i++) +- temp_area[i] = ebc_tolower(temp_area[i]); +- value = ebcstrtoul((char *)temp_area, &endptr, 10); ++ temp_area[i] = ebcdic_tolower(temp_area[i]); ++ value = ebcdic_strtoul((char *)temp_area, &endptr, 10); + + if ((endptr != temp_area) && (value < BOOT_MENU_ENTRIES - 1) && + (__stage2_params.config[value] != 0)) { +@@ -112,7 +113,7 @@ static int menu_param(unsigned long *val + int i; + + if (!sclp_param(loadparm)) +- *value = ebcstrtoul(loadparm, &endptr, 10); ++ *value = ebcdic_strtoul(loadparm, &endptr, 10); + + /* got number, done */ + if (endptr != loadparm) +@@ -121,7 +122,7 @@ static int menu_param(unsigned long *val + /* no number, check for keyword */ + i = 0; + /* skip leading whitespaces */ +- while ((i < PARAM_SIZE) && ebc_isspace(loadparm[i])) ++ while ((i < PARAM_SIZE) && ecbdic_isspace(loadparm[i])) + i++; + + if (!strncmp(&loadparm[i], "PROMPT", 6)) { +--- a/zipl/boot/stage3.c ++++ b/zipl/boot/stage3.c +@@ -12,9 +12,12 @@ + #include "libc.h" + #include "boot/sigp.h" + #include "boot/s390.h" ++#include "boot/sigp.h" + #include "stage3.h" + #include "error.h" + #include "zipl.h" ++#include "ebcdic.h" ++#include "ebcdic_conv.h" + + #define for_each_rb_entry(entry, rb) \ + for (entry = rb->entries; \ +@@ -24,159 +27,6 @@ + static const char *msg_sipl_inval = "Secure boot failure: invalid load address"; + static const char *msg_sipl_unverified = "Secure boot failure: unverified load address"; + +-static unsigned char ebc_037[256] = { +-/* 0x00 NUL SOH STX ETX *SEL HT *RNL DEL */ +- 0x00, 0x01, 0x02, 0x03, 0x07, 0x09, 0x07, 0x7F, +-/* 0x08 -GE -SPS -RPT VT FF CR SO SI */ +- 0x07, 0x07, 0x07, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, +-/* 0x10 DLE DC1 DC2 DC3 -RES -NL BS -POC +- -ENP ->LF */ +- 0x10, 0x11, 0x12, 0x13, 0x07, 0x0A, 0x08, 0x07, +-/* 0x18 CAN EM -UBS -CU1 -IFS -IGS -IRS -ITB +- -IUS */ +- 0x18, 0x19, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, +-/* 0x20 -DS -SOS FS -WUS -BYP LF ETB ESC +- -INP */ +- 0x07, 0x07, 0x1C, 0x07, 0x07, 0x0A, 0x17, 0x1B, +-/* 0x28 -SA -SFE -SM -CSP -MFA ENQ ACK BEL +- -SW */ +- 0x07, 0x07, 0x07, 0x07, 0x07, 0x05, 0x06, 0x07, +-/* 0x30 ---- ---- SYN -IR -PP -TRN -NBS EOT */ +- 0x07, 0x07, 0x16, 0x07, 0x07, 0x07, 0x07, 0x04, +-/* 0x38 -SBS -IT -RFF -CU3 DC4 NAK ---- SUB */ +- 0x07, 0x07, 0x07, 0x07, 0x14, 0x15, 0x07, 0x1A, +-/* 0x40 SP RSP ä ---- */ +- 0x20, 0xFF, 0x83, 0x84, 0x85, 0xA0, 0x07, 0x86, +-/* 0x48 . < ( + | */ +- 0x87, 0xA4, 0x9B, 0x2E, 0x3C, 0x28, 0x2B, 0x7C, +-/* 0x50 & ---- */ +- 0x26, 0x82, 0x88, 0x89, 0x8A, 0xA1, 0x8C, 0x07, +-/* 0x58 ß ! $ * ) ; */ +- 0x8D, 0xE1, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0xAA, +-/* 0x60 - / ---- Ä ---- ---- ---- */ +- 0x2D, 0x2F, 0x07, 0x8E, 0x07, 0x07, 0x07, 0x8F, +-/* 0x68 ---- , % _ > ? */ +- 0x80, 0xA5, 0x07, 0x2C, 0x25, 0x5F, 0x3E, 0x3F, +-/* 0x70 --- ---- ---- ---- ---- ---- ---- */ +- 0x07, 0x90, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, +-/* 0x78 * ` : # @ ' = " */ +- 0x70, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22, +-/* 0x80 * a b c d e f g */ +- 0x07, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, +-/* 0x88 h i ---- ---- ---- */ +- 0x68, 0x69, 0xAE, 0xAF, 0x07, 0x07, 0x07, 0xF1, +-/* 0x90 ° j k l m n o p */ +- 0xF8, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, +-/* 0x98 q r ---- ---- */ +- 0x71, 0x72, 0xA6, 0xA7, 0x91, 0x07, 0x92, 0x07, +-/* 0xA0 ~ s t u v w x */ +- 0xE6, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, +-/* 0xA8 y z ---- ---- ---- ---- */ +- 0x79, 0x7A, 0xAD, 0xAB, 0x07, 0x07, 0x07, 0x07, +-/* 0xB0 ^ ---- § ---- */ +- 0x5E, 0x9C, 0x9D, 0xFA, 0x07, 0x07, 0x07, 0xAC, +-/* 0xB8 ---- [ ] ---- ---- ---- ---- */ +- 0xAB, 0x07, 0x5B, 0x5D, 0x07, 0x07, 0x07, 0x07, +-/* 0xC0 { A B C D E F G */ +- 0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, +-/* 0xC8 H I ---- ö ---- */ +- 0x48, 0x49, 0x07, 0x93, 0x94, 0x95, 0xA2, 0x07, +-/* 0xD0 } J K L M N O P */ +- 0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, +-/* 0xD8 Q R ---- ü */ +- 0x51, 0x52, 0x07, 0x96, 0x81, 0x97, 0xA3, 0x98, +-/* 0xE0 \ S T U V W X */ +- 0x5C, 0xF6, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, +-/* 0xE8 Y Z ---- Ö ---- ---- ---- */ +- 0x59, 0x5A, 0xFD, 0x07, 0x99, 0x07, 0x07, 0x07, +-/* 0xF0 0 1 2 3 4 5 6 7 */ +- 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, +-/* 0xF8 8 9 ---- ---- Ü ---- ---- ---- */ +- 0x38, 0x39, 0x07, 0x07, 0x9A, 0x07, 0x07, 0x07 +-}; +- +-static unsigned char ebc_500[256] = { +-/* 0x00 NUL SOH STX ETX *SEL HT *RNL DEL */ +- 0x00, 0x01, 0x02, 0x03, 0x07, 0x09, 0x07, 0x7F, +-/* 0x08 -GE -SPS -RPT VT FF CR SO SI */ +- 0x07, 0x07, 0x07, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, +-/* 0x10 DLE DC1 DC2 DC3 -RES -NL BS -POC +- -ENP ->LF */ +- 0x10, 0x11, 0x12, 0x13, 0x07, 0x0A, 0x08, 0x07, +-/* 0x18 CAN EM -UBS -CU1 -IFS -IGS -IRS -ITB +- -IUS */ +- 0x18, 0x19, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, +-/* 0x20 -DS -SOS FS -WUS -BYP LF ETB ESC +- -INP */ +- 0x07, 0x07, 0x1C, 0x07, 0x07, 0x0A, 0x17, 0x1B, +-/* 0x28 -SA -SFE -SM -CSP -MFA ENQ ACK BEL +- -SW */ +- 0x07, 0x07, 0x07, 0x07, 0x07, 0x05, 0x06, 0x07, +-/* 0x30 ---- ---- SYN -IR -PP -TRN -NBS EOT */ +- 0x07, 0x07, 0x16, 0x07, 0x07, 0x07, 0x07, 0x04, +-/* 0x38 -SBS -IT -RFF -CU3 DC4 NAK ---- SUB */ +- 0x07, 0x07, 0x07, 0x07, 0x14, 0x15, 0x07, 0x1A, +-/* 0x40 SP RSP ä ---- */ +- 0x20, 0xFF, 0x83, 0x84, 0x85, 0xA0, 0x07, 0x86, +-/* 0x48 . < ( + | */ +- 0x87, 0xA4, 0x9B, 0x2E, 0x3C, 0x28, 0x2B, 0x7C, +-/* 0x50 & ---- */ +- 0x26, 0x82, 0x88, 0x89, 0x8A, 0xA1, 0x8C, 0x07, +-/* 0x58 ß ! $ * ) ; */ +- 0x8D, 0xE1, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0xAA, +-/* 0x60 - / ---- Ä ---- ---- ---- */ +- 0x2D, 0x2F, 0x07, 0x8E, 0x07, 0x07, 0x07, 0x8F, +-/* 0x68 ---- , % _ > ? */ +- 0x80, 0xA5, 0x07, 0x2C, 0x25, 0x5F, 0x3E, 0x3F, +-/* 0x70 --- ---- ---- ---- ---- ---- ---- */ +- 0x07, 0x90, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, +-/* 0x78 * ` : # @ ' = " */ +- 0x70, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22, +-/* 0x80 * a b c d e f g */ +- 0x07, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, +-/* 0x88 h i ---- ---- ---- */ +- 0x68, 0x69, 0xAE, 0xAF, 0x07, 0x07, 0x07, 0xF1, +-/* 0x90 ° j k l m n o p */ +- 0xF8, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, +-/* 0x98 q r ---- ---- */ +- 0x71, 0x72, 0xA6, 0xA7, 0x91, 0x07, 0x92, 0x07, +-/* 0xA0 ~ s t u v w x */ +- 0xE6, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, +-/* 0xA8 y z ---- ---- ---- ---- */ +- 0x79, 0x7A, 0xAD, 0xAB, 0x07, 0x07, 0x07, 0x07, +-/* 0xB0 ^ ---- § ---- */ +- 0x5E, 0x9C, 0x9D, 0xFA, 0x07, 0x07, 0x07, 0xAC, +-/* 0xB8 ---- [ ] ---- ---- ---- ---- */ +- 0xAB, 0x07, 0x5B, 0x5D, 0x07, 0x07, 0x07, 0x07, +-/* 0xC0 { A B C D E F G */ +- 0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, +-/* 0xC8 H I ---- ö ---- */ +- 0x48, 0x49, 0x07, 0x93, 0x94, 0x95, 0xA2, 0x07, +-/* 0xD0 } J K L M N O P */ +- 0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, +-/* 0xD8 Q R ---- ü */ +- 0x51, 0x52, 0x07, 0x96, 0x81, 0x97, 0xA3, 0x98, +-/* 0xE0 \ S T U V W X */ +- 0x5C, 0xF6, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, +-/* 0xE8 Y Z ---- Ö ---- ---- ---- */ +- 0x59, 0x5A, 0xFD, 0x07, 0x99, 0x07, 0x07, 0x07, +-/* 0xF0 0 1 2 3 4 5 6 7 */ +- 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, +-/* 0xF8 8 9 ---- ---- Ü ---- ---- ---- */ +- 0x38, 0x39, 0x07, 0x07, 0x9A, 0x07, 0x07, 0x07 +-}; +- +-static void ebcdic_to_ascii(unsigned char *target, unsigned char *source, +- unsigned int l) +-{ +- unsigned char *ebc; +- unsigned int i; +- +- ebc = is_zvm() ? ebc_037 : ebc_500; +- for (i = 0; i < l; i++) +- target[i] = ebc[source[i]]; +-} +- + static inline void __noreturn start_kernel(void) + { + struct psw_t *psw = &S390_lowcore.program_new_psw; diff --git a/s390-tools-sles15sp2-39-zipl-sclp-add-macros-for-the-control-program-masks.patch b/s390-tools-sles15sp2-39-zipl-sclp-add-macros-for-the-control-program-masks.patch new file mode 100644 index 0000000..633d5c4 --- /dev/null +++ b/s390-tools-sles15sp2-39-zipl-sclp-add-macros-for-the-control-program-masks.patch @@ -0,0 +1,79 @@ +Subject: [PATCH] [FEAT VS1804] zipl/sclp: add macros for the control-program masks +From: Marc Hartmayer + +Summary: genprotimg: Introduce new tool for the creation of PV images +Description: genprotimg takes a kernel, host-key documents, optionally an + initrd, optionally a file with the kernel command line, and it + generates a single, loadable image file. The image consists of a + concatenation of a plain text boot loader, the encrypted + components for kernel, initrd, and cmdline, and the + integrity-protected PV header, containing metadata necessary for + running the guest in PV mode. It's possible to use this image file + as a kernel for zIPL or for a direct kernel boot using QEMU. +Upstream-ID: 303a3707e2e59e0ad581876db426a52fffa606b0 +Problem-ID: VS1804 + +Upstream-Description: + + zipl/sclp: add macros for the control-program masks + + Add macros for the control-program masks and use them. + + Reviewed-by: Philipp Rudo + Reviewed-by: Stefan Haberland + Signed-off-by: Marc Hartmayer + Signed-off-by: Jan Höppner + + +Signed-off-by: Marc Hartmayer +--- + zipl/boot/sclp.c | 16 ++++++++-------- + zipl/boot/sclp.h | 6 ++++++ + 2 files changed, 14 insertions(+), 8 deletions(-) + +--- a/zipl/boot/sclp.c ++++ b/zipl/boot/sclp.c +@@ -126,20 +126,20 @@ int sclp_setup(int initialise) + + switch (initialise) { + case SCLP_INIT: +- sccb->receive_mask = 0x80000000; +- sccb->send_mask = 0x40000000; ++ sccb->receive_mask = SCLP_EVENT_MASK_OPCMD; ++ sccb->send_mask = SCLP_EVENT_MASK_MSG; + break; + case SCLP_DISABLE: +- sccb->receive_mask = 0x0; +- sccb->send_mask = 0x0; ++ sccb->receive_mask = SCLP_EVENT_MASK_DISABLE; ++ sccb->send_mask = SCLP_EVENT_MASK_DISABLE; + break; + case SCLP_HSA_INIT: +- sccb->receive_mask = 0x0; +- sccb->send_mask = 0x40000010; ++ sccb->receive_mask = SCLP_EVENT_MASK_DISABLE; ++ sccb->send_mask = SCLP_EVENT_MASK_MSG | SCLP_EVENT_MASK_SDIAS; + break; + case SCLP_HSA_INIT_ASYNC: +- sccb->receive_mask = 0x00000010; +- sccb->send_mask = 0x40000010; ++ sccb->receive_mask = SCLP_EVENT_MASK_SDIAS; ++ sccb->send_mask = SCLP_EVENT_MASK_MSG | SCLP_EVENT_MASK_SDIAS; + break; + } + +--- a/zipl/boot/sclp.h ++++ b/zipl/boot/sclp.h +@@ -28,6 +28,12 @@ + #define SCLP_CMD_READ_INFO2 0x00020001 + #define SCLP_CMD_READ_DATA 0x00770005 + ++/* SCLP event masks */ ++#define SCLP_EVENT_MASK_DISABLE 0x00000000 ++#define SCLP_EVENT_MASK_SDIAS 0x00000010 ++#define SCLP_EVENT_MASK_MSG 0x40000000 ++#define SCLP_EVENT_MASK_OPCMD 0x80000000 ++ + #define PSW_EXT_MASK 0x00080000ULL + #define PSW_EXT_ADDR 0x80000000ULL + #define PSW_WAIT_MASK 0x010a0000ULL diff --git a/s390-tools-sles15sp2-40-zipl-sclp-add-sclp_print_ascii.patch b/s390-tools-sles15sp2-40-zipl-sclp-add-sclp_print_ascii.patch new file mode 100644 index 0000000..ff94983 --- /dev/null +++ b/s390-tools-sles15sp2-40-zipl-sclp-add-sclp_print_ascii.patch @@ -0,0 +1,163 @@ +Subject: [PATCH] [FEAT VS1804] zipl/sclp: add `sclp_print_ascii` +From: Marc Hartmayer + +Summary: genprotimg: Introduce new tool for the creation of PV images +Description: genprotimg takes a kernel, host-key documents, optionally an + initrd, optionally a file with the kernel command line, and it + generates a single, loadable image file. The image consists of a + concatenation of a plain text boot loader, the encrypted + components for kernel, initrd, and cmdline, and the + integrity-protected PV header, containing metadata necessary for + running the guest in PV mode. It's possible to use this image file + as a kernel for zIPL or for a direct kernel boot using QEMU. +Upstream-ID: f99560f734e8101a0e8195d73e3350d9211335b8 +Problem-ID: VS1804 + +Upstream-Description: + + zipl/sclp: add `sclp_print_ascii` + + Add `sclp_print_ascii` function that can be used to print output on + the SCLP ASCII console. This would increase the size of the + loaders (e.g. eckd2.bin and fba2.bin) and therefore might break the + compilation. In order to avoid that add a macro 'ENABLE_SCLP_ASCII' + which must be defined by the users of the `sclp_print_ascii` function. + + Reviewed-by: Philipp Rudo + Reviewed-by: Stefan Haberland + Signed-off-by: Marc Hartmayer + Signed-off-by: Jan Höppner + + +Signed-off-by: Marc Hartmayer +--- + zipl/boot/sclp.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ + zipl/boot/sclp.h | 20 +++++++++++++++++++- + 2 files changed, 69 insertions(+), 1 deletion(-) + +--- a/zipl/boot/sclp.c ++++ b/zipl/boot/sclp.c +@@ -13,6 +13,10 @@ + #include "error.h" + #include "boot/s390.h" + #include "sclp.h" ++#include "ebcdic.h" ++#ifdef ENABLE_SCLP_ASCII ++# include "ebcdic_conv.h" ++#endif /* ENABLE_SCLP_ASCII */ + + /* Perform service call. Return 0 on success, non-zero otherwise. */ + static int sclp_service_call(unsigned int command, void *sccb) +@@ -133,6 +137,10 @@ int sclp_setup(int initialise) + sccb->receive_mask = SCLP_EVENT_MASK_DISABLE; + sccb->send_mask = SCLP_EVENT_MASK_DISABLE; + break; ++ case SCLP_LINE_ASCII_INIT: ++ sccb->receive_mask = SCLP_EVENT_MASK_DISABLE; ++ sccb->send_mask = SCLP_EVENT_MASK_MSG | SCLP_EVENT_MASK_ASCII; ++ break; + case SCLP_HSA_INIT: + sccb->receive_mask = SCLP_EVENT_MASK_DISABLE; + sccb->send_mask = SCLP_EVENT_MASK_MSG | SCLP_EVENT_MASK_SDIAS; +@@ -161,6 +169,48 @@ out_free_page: + return rc; + } + ++#ifdef ENABLE_SCLP_ASCII ++/* Content of @buffer must be EBCDIC encoded. The function used for ++ * the conversion `ebcdic_to_ascii` differentiates whether the code ++ * runs on z/VM or not and then selects the appropriate EBCDIC ++ * coding. ++ */ ++int sclp_print_ascii(const char *buffer) ++{ ++ struct write_sccb *sccb = NULL; ++ int rc, str_len = strlen(buffer); ++ unsigned long data_len = str_len + 1; ++ ++ /* don't overflow the sccb buffer */ ++ if (data_len > SCCB_MAX_DATA_LEN) ++ data_len = SCCB_MAX_DATA_LEN; ++ ++ sccb = (void *)get_zeroed_page(); ++ sccb->header.length = sizeof(struct write_sccb) - sizeof(struct mdb) ++ + data_len; ++ sccb->header.function_code = SCLP_FC_NORMAL_WRITE; ++ sccb->msg_buf.header.length = sizeof(struct msg_buf) - sizeof(struct mdb) ++ + data_len; ++ sccb->msg_buf.header.type = SCLP_EVENT_DATA_ASCII; ++ sccb->msg_buf.header.flags = 0; ++ ebcdic_to_ascii(sccb->msg_buf.data, ++ (const unsigned char *)buffer, ++ data_len - 1); ++ sccb->msg_buf.data[data_len - 1] = '\0'; ++ ++ /* SCLP command for write data */ ++ rc = start_sclp(SCLP_CMD_WRITE_DATA, sccb); ++ if (rc || sccb->header.response_code != 0x20) { ++ rc = 1; ++ goto out_free_page; ++ } ++ rc = 0; ++out_free_page: ++ free_page((unsigned long) sccb); ++ return rc; ++} ++#endif /* ENABLE_SCLP_ASCII */ ++ + int sclp_print(char *buffer) + { + struct write_sccb *sccb; +--- a/zipl/boot/sclp.h ++++ b/zipl/boot/sclp.h +@@ -28,9 +28,16 @@ + #define SCLP_CMD_READ_INFO2 0x00020001 + #define SCLP_CMD_READ_DATA 0x00770005 + ++/* SCLP function codes */ ++#define SCLP_FC_NORMAL_WRITE 0 ++ ++/* SCLP event data types */ ++#define SCLP_EVENT_DATA_ASCII 0x1a ++ + /* SCLP event masks */ + #define SCLP_EVENT_MASK_DISABLE 0x00000000 + #define SCLP_EVENT_MASK_SDIAS 0x00000010 ++#define SCLP_EVENT_MASK_ASCII 0x00000040 + #define SCLP_EVENT_MASK_MSG 0x40000000 + #define SCLP_EVENT_MASK_OPCMD 0x80000000 + +@@ -46,6 +53,11 @@ + #define SCLP_DISABLE 0x1 + #define SCLP_HSA_INIT 0x2 + #define SCLP_HSA_INIT_ASYNC 0x3 ++#define SCLP_LINE_ASCII_INIT 0x4 ++ ++#define SCCB_SIZE PAGE_SIZE ++#define SCCB_MAX_DATA_LEN (SCCB_SIZE - sizeof(struct sccb_header) \ ++ - sizeof(struct evbuf_header)) + + typedef uint32_t sccb_mask_t; + +@@ -114,7 +126,10 @@ struct mdb { + + struct msg_buf { + struct evbuf_header header; +- struct mdb mdb; ++ union { ++ struct mdb mdb; ++ uint8_t data[0]; ++ }; + } __packed; + + struct write_sccb { +@@ -164,6 +179,9 @@ struct read_sccb { + int start_sclp(unsigned int, void *); + int sclp_setup(int); + int sclp_print(char *); ++# ifdef ENABLE_SCLP_ASCII ++int sclp_print_ascii(const char *); ++# endif /* ENABLE_SCLP_ASCII */ + int sclp_param(char *); + int sclp_read(unsigned long, void *, int *); + int sclp_read_info(struct read_info_sccb *sccb); diff --git a/s390-tools-sles15sp2-41-zipl-libc-printf-print-on-linemode-and-ASCII-console.patch b/s390-tools-sles15sp2-41-zipl-libc-printf-print-on-linemode-and-ASCII-console.patch new file mode 100644 index 0000000..38499c0 --- /dev/null +++ b/s390-tools-sles15sp2-41-zipl-libc-printf-print-on-linemode-and-ASCII-console.patch @@ -0,0 +1,47 @@ +Subject: [PATCH] [FEAT VS1804] zipl/libc: printf: print on linemode and ASCII console +From: Marc Hartmayer + +Summary: genprotimg: Introduce new tool for the creation of PV images +Description: genprotimg takes a kernel, host-key documents, optionally an + initrd, optionally a file with the kernel command line, and it + generates a single, loadable image file. The image consists of a + concatenation of a plain text boot loader, the encrypted + components for kernel, initrd, and cmdline, and the + integrity-protected PV header, containing metadata necessary for + running the guest in PV mode. It's possible to use this image file + as a kernel for zIPL or for a direct kernel boot using QEMU. +Upstream-ID: e51663bbca8770c1f7986dac47a59193dbf96010 +Problem-ID: VS1804 + +Upstream-Description: + + zipl/libc: printf: print on linemode and ASCII console + + ... if the `ENABLE_SCLP_ASCII` macro is defined. + + Reviewed-by: Philipp Rudo + Reviewed-by: Stefan Haberland + Signed-off-by: Marc Hartmayer + Signed-off-by: Jan Höppner + + +Signed-off-by: Marc Hartmayer +--- + zipl/boot/libc.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/zipl/boot/libc.c ++++ b/zipl/boot/libc.c +@@ -406,8 +406,11 @@ void printf(const char *fmt, ...) + buf[LINE_LENGTH - 2] = '.'; + buf[LINE_LENGTH - 3] = '.'; + } +- sclp_print(buf); + va_end(va); ++ sclp_print(buf); ++#ifdef ENABLE_SCLP_ASCII ++ sclp_print_ascii(buf); ++#endif /* ENABLE_SCLP_ASCII */ + } + + /* diff --git a/s390-tools-sles15sp2-42-Consolidate-ALIGN-__ALIGN_MASK-ARRAY_SIZE-macros.patch b/s390-tools-sles15sp2-42-Consolidate-ALIGN-__ALIGN_MASK-ARRAY_SIZE-macros.patch new file mode 100644 index 0000000..ceec37a --- /dev/null +++ b/s390-tools-sles15sp2-42-Consolidate-ALIGN-__ALIGN_MASK-ARRAY_SIZE-macros.patch @@ -0,0 +1,134 @@ +Subject: [PATCH] [FEAT VS1804] Consolidate `ALIGN, __ALIGN_MASK, ARRAY_SIZE` macros +From: Marc Hartmayer + +Summary: genprotimg: Introduce new tool for the creation of PV images +Description: genprotimg takes a kernel, host-key documents, optionally an + initrd, optionally a file with the kernel command line, and it + generates a single, loadable image file. The image consists of a + concatenation of a plain text boot loader, the encrypted + components for kernel, initrd, and cmdline, and the + integrity-protected PV header, containing metadata necessary for + running the guest in PV mode. It's possible to use this image file + as a kernel for zIPL or for a direct kernel boot using QEMU. +Upstream-ID: 67aef9bbf3b5d18c70e8c4a45734bcb6d6744a8c +Problem-ID: VS1804 + +Upstream-Description: + + Consolidate `ALIGN, __ALIGN_MASK, ARRAY_SIZE` macros + + Consolidate `ALIGN, __ALIGN_MASK, ARRAY_SIZE` macros and add them to + lib/zt_common.h. While at it, adapt coding style. + + Reviewed-by: Philipp Rudo + Reviewed-by: Stefan Haberland + Signed-off-by: Marc Hartmayer + Signed-off-by: Jan Höppner + + +Signed-off-by: Marc Hartmayer +--- + cmsfs-fuse/dasd.c | 1 + + cmsfs-fuse/helper.h | 2 -- + include/lib/zt_common.h | 4 ++++ + zconf/qeth/misc.h | 2 -- + zdev/include/misc.h | 2 +- + zdump/zg.c | 2 +- + zdump/zg.h | 3 --- + zipl/include/zipl.h | 4 ---- + 8 files changed, 7 insertions(+), 13 deletions(-) + +--- a/cmsfs-fuse/dasd.c ++++ b/cmsfs-fuse/dasd.c +@@ -19,6 +19,7 @@ + #include + #include + ++#include "lib/zt_common.h" + #include "cmsfs-fuse.h" + #include "edf.h" + #include "helper.h" +--- a/cmsfs-fuse/helper.h ++++ b/cmsfs-fuse/helper.h +@@ -49,6 +49,4 @@ extern FILE *logfile; + fprintf(stderr, COMP "Warning, " __VA_ARGS__); \ + } while (0) + +-#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) +- + #endif +--- a/include/lib/zt_common.h ++++ b/include/lib/zt_common.h +@@ -44,6 +44,10 @@ + # define STATIC_ASSERT(test) + #endif + ++#define ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a) - 1) ++#define __ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask)) ++#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) ++ + #define RELEASE_STRING STRINGIFY (S390_TOOLS_RELEASE) + #define TOOLS_LIBDIR STRINGIFY (S390_TOOLS_LIBDIR) + #define TOOLS_SYSCONFDIR STRINGIFY (S390_TOOLS_SYSCONFDIR) +--- a/zconf/qeth/misc.h ++++ b/zconf/qeth/misc.h +@@ -12,8 +12,6 @@ + + #include + +-#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) +- + char *misc_link_target(const char *fmt, ...); + bool misc_str_in_list(const char *str, const char *strings[], int array_size); + int misc_argz_add_from_file(char **argz, size_t *argz_len, +--- a/zdev/include/misc.h ++++ b/zdev/include/misc.h +@@ -15,10 +15,10 @@ + #include + #include + ++#include "lib/zt_common.h" + #include "lib/util_list.h" + #include "exit_code.h" + +-#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) + #define SCOPE_ACTIVE(x) ((x) & config_active ? 1 : 0) + #define SCOPE_PERSISTENT(x) ((x) & config_persistent ? 1 : 0) + #define SCOPE_AUTOCONF(x) ((x) & config_autoconf ? 1 : 0) +--- a/zdump/zg.c ++++ b/zdump/zg.c +@@ -432,7 +432,7 @@ char *zg_devnode_create(dev_t dev) + char *file_path; + unsigned int i; + +- for (i = 0; i < ARRAY_ELEMENT_CNT(dir_vec); i++) { ++ for (i = 0; i < ARRAY_SIZE(dir_vec); i++) { + if (dir_vec[i] == NULL) + continue; + file_path = devnode_create_dir(dir_vec[i], dev); +--- a/zdump/zg.h ++++ b/zdump/zg.h +@@ -122,10 +122,7 @@ do { \ + * Misc + */ + #define PAGE_SIZE 4096UL +-#define ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a)-1) +-#define __ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask)) + #define PAGE_ALIGN(addr) ALIGN(addr, PAGE_SIZE) +-#define ARRAY_ELEMENT_CNT(x) (sizeof(x) / sizeof(x[0])) + #define ROUNDUP(x, y) ((((x) + ((y) - 1)) / (y)) * (y)) + + static inline u32 zg_csum_partial(const void *buf, int len, u32 sum) +--- a/zipl/include/zipl.h ++++ b/zipl/include/zipl.h +@@ -62,10 +62,6 @@ typedef uint64_t address_t; + * resulting return code or 0. */ + #define DRY_RUN_FUNC(x) (dry_run ? 0 : (x)) + +-#define ALIGN(x,a) __ALIGN_MASK(x,(typeof(x))(a)-1) +-#define __ALIGN_MASK(x,mask) (((x)+(mask))&~(mask)) +-#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) +- + extern int verbose; + extern int interactive; + extern int dry_run; diff --git a/s390-tools-sles15sp2-43-genprotimg-boot-initial-bootloader-support.patch b/s390-tools-sles15sp2-43-genprotimg-boot-initial-bootloader-support.patch new file mode 100644 index 0000000..5270fc7 --- /dev/null +++ b/s390-tools-sles15sp2-43-genprotimg-boot-initial-bootloader-support.patch @@ -0,0 +1,803 @@ +Subject: [PATCH] [FEAT VS1804] genprotimg: boot: initial bootloader support +From: Marc Hartmayer + +Summary: genprotimg: Introduce new tool for the creation of PV images +Description: genprotimg takes a kernel, host-key documents, optionally an + initrd, optionally a file with the kernel command line, and it + generates a single, loadable image file. The image consists of a + concatenation of a plain text boot loader, the encrypted + components for kernel, initrd, and cmdline, and the + integrity-protected PV header, containing metadata necessary for + running the guest in PV mode. It's possible to use this image file + as a kernel for zIPL or for a direct kernel boot using QEMU. +Upstream-ID: 3356d6f4facd748f8f5cf24ffc5056db3e915f2c +Problem-ID: VS1804 + +Upstream-Description: + + genprotimg: boot: initial bootloader support + + Add a boot loader for protected virtualization (PV) that can be + combined with a kernel/initrd/parmfile to form a single bootable file. + This file must be constructed in a way that it can be used (1) for a + QEMU direct kernel boot and (2) it can be zipl'ed by the normal, + unmodified zipl program. + + This new boot loader consists of two parts: + + 1. stage3a boot loader (cleartext), this loader is responsible for + the transition into the protected mode by doing diag308 subcode 8 + and 10 calls. + + 2. stage3b boot loader (encrypted), this loader is very similar to the + normal zipl stage3 boot loader. It will be loaded by the Ultravisor + after the successful transition into protected mode. Like the zipl + stage3 boot loader it moves the kernel and patches in the values + for initrd and parmline. + + The requirements for (1) and (2) result in the following constraints: + + 1. It must be possible to place stage3a and stage3b at a location >= + 0x10000 because the zipl stage3 loader zeroes out everything at + addresses lower than 0x10000 of the image. + + 2. As the stage3 loader of zipl assumes that the passed kernel image + looks like a normal kernel image, the zipl stage3 loader modifies the + content at the memory area 0x10400 - 0x10800, therefore we leave this + area unused in our stage3a loader. + + 3. The default entry address used by the zipl stage3 loader is 0x10000 + so we add a simple branch to 0x11000 at 0x10000 so the zipl stage3 + loader can modify the area 0x10400 - 0x10800 without affecting the + stage3a loader. + + The stage3b loader is linked at address 0x9000, therefore it will not + work at another address. The relocation support for the stage3b + loader, so that it can be placed at addresses != 0x9000, is added in + the next patch. This loader with relocation support has the name + 'stage3b_reloc'. + + The memory layout of the single bootable file looks like: + + +-----------------------+-----------+------------------------+ + |Start |End |Use | + +=======================+===========+========================+ + |0 |0x7 |Short PSW, starting | + | | |instruction at 0x11000 | + +-----------------------+-----------+------------------------+ + |0x10000 |0x10012 |Branch to 0x11000 | + +-----------------------+-----------+------------------------+ + |0x10013 |0x10fff |Left intentionally | + | | |unused | + +-----------------------+-----------+------------------------+ + |0x11000 |0x12fff |Stage3a | + +-----------------------+-----------+------------------------+ + |0x13000 |0x13fff |IPIB used as argument | + | | |for the diag308 call | + +-----------------------+-----------+------------------------+ + |0x14000 |0x1[45]fff |UV header used for the | + | | |diag308 call (size can | + | | |be either 1 or 2 pages) | + +-----------------------+-----------+------------------------+ + |NEXT_PAGE_ALIGNED_ADDR | |Encrypted Kernel | + +-----------------------+-----------+------------------------+ + |NEXT_PAGE_ALIGNED_ADDR | |Encrypted Cmdline | + +-----------------------+-----------+------------------------+ + |NEXT_PAGE_ALIGNED_ADDR | |Encrypted Initrd | + +-----------------------+-----------+------------------------+ + |NEXT_PAGE_ALIGNED_ADDR | |Encrypted Stage3b_reloc | + +-----------------------+-----------+------------------------+ + + Reviewed-by: Philipp Rudo + Signed-off-by: Marc Hartmayer + Signed-off-by: Jan Höppner + + +Signed-off-by: Marc Hartmayer +--- + genprotimg/boot/.gitignore | 3 + genprotimg/boot/Makefile | 83 +++++++++++++++++++++++++++ + genprotimg/boot/common_memory_layout.h | 25 ++++++++ + genprotimg/boot/head.S | 29 +++++++++ + genprotimg/boot/stage3a.c | 62 ++++++++++++++++++++ + genprotimg/boot/stage3a.h | 34 +++++++++++ + genprotimg/boot/stage3a.lds | 101 +++++++++++++++++++++++++++++++++ + genprotimg/boot/stage3a_init.S | 26 ++++++++ + genprotimg/boot/stage3b.c | 77 +++++++++++++++++++++++++ + genprotimg/boot/stage3b.h | 38 ++++++++++++ + genprotimg/boot/stage3b.lds | 87 ++++++++++++++++++++++++++++ + include/boot/ipl.h | 25 ++++++++ + include/boot/s390.h | 22 +++++-- + zipl/boot/error.h | 6 + + 14 files changed, 613 insertions(+), 5 deletions(-) + +--- /dev/null ++++ b/genprotimg/boot/.gitignore +@@ -0,0 +1,3 @@ ++*.elf ++*.bin ++*.d +--- /dev/null ++++ b/genprotimg/boot/Makefile +@@ -0,0 +1,83 @@ ++# Common definitions ++include ../../common.mak ++ ++ZIPL_DIR := $(rootdir)/zipl ++ZIPL_BOOT_DIR := $(ZIPL_DIR)/boot ++ ++INCLUDE_PATHS := $(ZIPL_BOOT_DIR) $(ZIPL_DIR)/include $(rootdir)/include ++INCLUDE_PARMS := $(addprefix -I,$(INCLUDE_PATHS)) ++ ++ALL_CFLAGS := $(NO_PIE_CFLAGS) -Os -g \ ++ $(INCLUDE_PARMS) \ ++ -DENABLE_SCLP_ASCII=1 \ ++ -DS390_TOOLS_RELEASE=$(S390_TOOLS_RELEASE) \ ++ -fno-builtin -ffreestanding -fno-asynchronous-unwind-tables \ ++ -fno-delete-null-pointer-checks \ ++ -fexec-charset=IBM1047 -m64 -mpacked-stack \ ++ -mstack-size=4096 -mstack-guard=128 -msoft-float \ ++ -Wall -Wformat-security -Wextra -Werror ++ ++FILES := stage3a.bin stage3b.bin ++ ++ZIPL_SRCS_C := libc.c ebcdic.c ebcdic_conv.c sclp.c ++ZIPL_SRCS_ASM := entry.S ++ ++ZIPL_OBJS_C := $(ZIPL_SRCS_C:%.c=%.o) ++ZIPL_OBJS_ASM := $(ZIPL_SRCS_ASM:%.S=%.o) ++ZIPL_OBJS := $(ZIPL_OBJS_C) $(ZIPL_OBJS_ASM) ++ ++ ++all: $(FILES) ++ ++# Prevent make from using some default rules... ++%: %.S ++ ++%.o: %.S Makefile ++ $(CC) $(ALL_CFLAGS) -c -o $@ $< ++ ++%.o: %.c Makefile ++ $(CC) $(ALL_CFLAGS) -c -o $@ $< ++ ++ ++# Special rules for zipl object files ++$(ZIPL_OBJS_C): %.o : $(ZIPL_BOOT_DIR)/%.c ++ $(CC) $(ALL_CFLAGS) -c -o $@ $< ++ ++$(ZIPL_OBJS_ASM): %.o : $(ZIPL_BOOT_DIR)/%.S ++ $(CC) $(ALL_CFLAGS) -c -o $@ $< ++ ++dependencies_zipl_c := $(ZIPL_SRCS_C:%.c=.%.o.d) ++ ++$(dependencies_zipl_c): .%.o.d : $(ZIPL_BOOT_DIR)/%.c ++ $(CC_SILENT) -MM $(ALL_CPPFLAGS) $(ALL_CFLAGS) $< > $@ ++ ++ifneq ($(MAKECMDGOALS),clean) ++-include $(dependencies_zipl_c) ++endif ++ ++ ++stage3a.elf: head.o stage3a_init.o stage3a.o stage3a.lds $(ZIPL_OBJS) ++stage3b.elf: head.o stage3b.o stage3b.lds $(ZIPL_OBJS) ++ ++%.elf: %.o ++ case $* in \ ++ stage3a) SFLAGS="$(NO_PIE_LINKFLAGS) -nostdlib -Wl,-T,stage3a.lds";; \ ++ stage3b) SFLAGS="$(NO_PIE_LINKFLAGS) -nostdlib -Wl,-T,stage3b.lds";; \ ++ esac; \ ++ $(LINK) $$SFLAGS -m64 $(filter %.o, $^) -o $@ ++ @chmod a-x $@ ++ ++%.bin: %.elf ++ $(OBJCOPY) -O binary \ ++ --only-section=.text* \ ++ --only-section=.ex_table* \ ++ --only-section=.fixup* \ ++ --only-section=.data* \ ++ --only-section=.rodata* \ ++ $< $@ ++ @chmod a-x $@ ++ ++clean: ++ rm -f *.o *.elf *.bin *.map .*.d ++ ++.PHONY: all clean +--- /dev/null ++++ b/genprotimg/boot/common_memory_layout.h +@@ -0,0 +1,25 @@ ++/* ++ * Common memory layout for stage3a and stage3b bootloader. ++ * ++ * Copyright IBM Corp. 2020 ++ * ++ * s390-tools is free software; you can redistribute it and/or modify ++ * it under the terms of the MIT license. See LICENSE for details. ++ */ ++ ++#ifndef COMMON_MEMORY_LAYOUT_H ++#define COMMON_MEMORY_LAYOUT_H ++ ++#include "boot/loaders_layout.h" ++ ++#define STACK_ADDRESS STAGE3_STACK_ADDRESS ++#define STACK_SIZE STAGE3_STACK_SIZE ++ ++#define HEAP_ADDRESS STAGE3_HEAP_ADDRESS ++#define HEAP_SIZE STAGE3_HEAP_SIZE ++ ++ ++#ifndef __ASSEMBLER__ ++ ++#endif /* __ASSEMBLER__ */ ++#endif /* COMMON_MEMORY_LAYOUT_H */ +--- /dev/null ++++ b/genprotimg/boot/head.S +@@ -0,0 +1,29 @@ ++/* ++ * Entry code for stage 3a boot loader ++ * ++ * Copyright IBM Corp. 2020 ++ * ++ * s390-tools is free software; you can redistribute it and/or modify ++ * it under the terms of the MIT license. See LICENSE for details. ++ */ ++ ++ ++#include "common_memory_layout.h" ++ ++#include "boot/s390.h" ++#include "boot/sigp.h" ++ ++.section .text.start ++.globl _start ++_start: ++ /* Might be called after a diag308 so better set ++ * architecture and addressing mode ++ */ ++ lhi %r1, 1 ++ sigp %r1, %r0, SIGP_SET_ARCHITECTURE ++ sam64 ++ ++ /* Initialize stack */ ++ lgfi %r15, STACK_ADDRESS + STACK_SIZE - STACK_FRAME_OVERHEAD ++ brasl %r14, initialize ++.previous +--- /dev/null ++++ b/genprotimg/boot/stage3a.c +@@ -0,0 +1,62 @@ ++/* ++ * Main program for stage3a bootloader ++ * ++ * Copyright IBM Corp. 2020 ++ * ++ * s390-tools is free software; you can redistribute it and/or modify ++ * it under the terms of the MIT license. See LICENSE for details. ++ */ ++ ++#include "libc.h" ++#include "stage3a.h" ++ ++#include "lib/zt_common.h" ++#include "boot/s390.h" ++#include "boot/ipl.h" ++#include "sclp.h" ++#include "error.h" ++ ++ ++static volatile struct stage3a_args __section(".loader_parms") loader_parms; ++ ++void __noreturn start(void) ++{ ++ int rc; ++ volatile struct stage3a_args *args = &loader_parms; ++ /* calculate the IPIB memory address */ ++ struct ipl_parameter_block *ipib = (void *)((uint64_t)args + args->ipib_offs); ++ ++ /* Calculate the PV header memory address and set it and its ++ * size in the IPIB. This allows the PV header to be position ++ * independent. ++ */ ++ ipib->pv.pv_hdr_addr = (uint64_t)args + args->hdr_offs; ++ ipib->pv.pv_hdr_size = args->hdr_size; ++ ++ /* set up ASCII and line-mode */ ++ sclp_setup(SCLP_LINE_ASCII_INIT); ++ ++ /* test if Secure Execution Unpack facility is available */ ++ stfle(S390_lowcore.stfle_fac_list, ++ ARRAY_SIZE(S390_lowcore.stfle_fac_list)); ++ rc = test_facility(UNPACK_FACILITY); ++ if (rc == 0) ++ panic(ENOPV, "Secure unpack facility is not available\n"); ++ ++ rc = diag308(DIAG308_SET_PV, ipib); ++ if (rc != DIAG308_RC_OK) ++ panic(EPV, "Protected boot setup has failed: 0x%x\n", rc); ++ ++ rc = diag308(DIAG308_UNPACK_PV, 0x0); ++ if (rc != DIAG308_RC_OK) { ++ sclp_setup(SCLP_LINE_ASCII_INIT); ++ panic(EPV, "Protected boot has failed: 0x%x\n", rc); ++ } ++ ++ while (1) ++ ; ++} ++ ++void panic_notify(unsigned long UNUSED(rc)) ++{ ++} +--- /dev/null ++++ b/genprotimg/boot/stage3a.h +@@ -0,0 +1,34 @@ ++/* ++ * Main program for stage3a bootloader. ++ * ++ * Copyright IBM Corp. 2020 ++ * ++ * s390-tools is free software; you can redistribute it and/or modify ++ * it under the terms of the MIT license. See LICENSE for details. ++ */ ++ ++#ifndef STAGE3A_H ++#define STAGE3A_H ++ ++#include "lib/zt_common.h" ++#include "boot/loaders_layout.h" ++ ++#define STAGE3A_INIT_ENTRY IMAGE_ENTRY ++#define STAGE3A_ENTRY (STAGE3A_INIT_ENTRY + _AC(0x1000, UL)) ++#define STAGE3A_LOAD_ADDRESS IMAGE_LOAD_ADDRESS ++ ++ ++#ifndef __ASSEMBLER__ ++ ++#include ++ ++/* Must not have any padding */ ++struct stage3a_args { ++ uint64_t hdr_offs; ++ uint64_t hdr_size; ++ uint64_t ipib_offs; ++}; ++STATIC_ASSERT(sizeof(struct stage3a_args) == 3 * 8) ++ ++#endif /* __ASSEMBLER__ */ ++#endif /* STAGE3A_H */ +--- /dev/null ++++ b/genprotimg/boot/stage3a.lds +@@ -0,0 +1,101 @@ ++/* ++ * Memory layout for stage 3a ++ * ========================== ++ * ++ * General memory layout ++ * --------------------- ++ * ++ * 0x00000 - 0x01fff Lowcore ++ * 0x02000 - 0x05fff Memory allocation (heap) ++ * 0x0f000 - 0x0ffff Stack ++ * 0x10000 - 0x10012 Jump to the "actual" stage3a code ++ * 0x11000 - 0x12fff Stage3a code + arguments (offsets and lengths to the ++ * actual data: IPIB and UV header) ++ */ ++ ++OUTPUT_FORMAT("elf64-s390", "elf64-s390", "elf64-s390") ++OUTPUT_ARCH(s390:64-bit) ++ ++ENTRY(_init) ++ ++__heap_size__ = 0x4000; ++__stack_size__ = 0x1000; ++ ++SECTIONS ++{ ++ . = 0x0; ++ ++ . = 0x2000; ++ __heap_start = .; ++ .heap : { ++ . = . + __heap_size__; ++ ASSERT(__heap_stop - __heap_start == __heap_size__, ++ "Heap section doesn't conform to the described memory layout"); ++ } ++ __heap_stop = .; ++ ++ . = 0xf000; ++ __stack_start = .; ++ .stack : { ++ . = . + __stack_size__; ++ ASSERT(__stack_end - __stack_start == __stack_size__, ++ "Stack section doesn't conform to the described memory layout"); ++ } ++ __stack_end = .; ++ ++ . = 0x10000; ++ __text_init_start = .; ++ .text : { ++ stage3a_init.o(.text.init) ++ __text_init_stop = ABSOLUTE(.); ++ /* Text size of text_init must be smaller than 'PARMAREA - IMAGE_ENTRY', ++ * otherwise the text data could be overwritten by the original zipl stage3 ++ * boot loader */ ++ ASSERT(__text_init_stop - __text_init_start < 0x400, ++ "Text size must be smaller than 'PARMAREA - IMAGE_ENTRY'"); ++ . = 0x1000; ++ head.o(.text.start) ++ *(.text) ++ } ++ ++ .ex_table ALIGN(16) : { ++ __ex_table_start = .; ++ *(.ex_table) ++ __ex_table_stop = .; ++ } ++ ++ .bss ALIGN(16) : { ++ __bss_start = .; ++ *(.bss) ++ __bss_stop = .; ++ } ++ ++ .rodata ALIGN(16) : { ++ *(.rodata) ++ *(.rodata.*) ++ } ++ ++ .data ALIGN(16) : { ++ *(.data) ++ . = ALIGN(16); ++ /* The IPIB offset and the UV header offset and size will be ++ * saved in 'loader_parms' */ ++ __loader_parms_start = .; ++ KEEP(*(.loader_parms)); ++ __loader_parms_stop = .; ++ ASSERT(__loader_parms_stop - __loader_parms_start == 3 * 8, ++ "Data size must be equal to 'sizeof(struct stage3a_args)'"); ++ ASSERT(ABSOLUTE(.) < 0x13000, "Data section doesn't conform to the described memory layout"); ++ } ++ ++ /* List this explicitly as otherwise .note.gnu.build-id will be ++ * put at 0x0 */ ++ .notes : { ++ *(.note.*) ++ } ++ ++ /* Sections to be discarded */ ++ /DISCARD/ : { ++ *(.eh_frame) ++ } ++} +--- /dev/null ++++ b/genprotimg/boot/stage3a_init.S +@@ -0,0 +1,26 @@ ++/* ++ * Entry code for stage 3a boot loader ++ * ++ * Copyright IBM Corp. 2020 ++ * ++ * s390-tools is free software; you can redistribute it and/or modify ++ * it under the terms of the MIT license. See LICENSE for details. ++ */ ++ ++#include "stage3a.h" ++#include "boot/sigp.h" ++ ++.section .text.init ++.globl _init ++_init: ++ /* set architecture and switch to 64bit */ ++ lhi %r1, 1 ++ sigp %r1, %r0, SIGP_SET_ARCHITECTURE ++ sam64 ++ /* The original stage3 boot loader will try to store the ++ * kernel command line and the address and size of the ++ * ramdisk. Simply ignore this by starting at 0x11000. ++ */ ++ lgfi %r1, STAGE3A_ENTRY ++ br %r1 ++.previous +--- /dev/null ++++ b/genprotimg/boot/stage3b.c +@@ -0,0 +1,77 @@ ++/* ++ * Main program for stage3b bootloader ++ * ++ * Copyright IBM Corp. 2020 ++ * ++ * s390-tools is free software; you can redistribute it and/or modify ++ * it under the terms of the MIT license. See LICENSE for details. ++ */ ++ ++#include "libc.h" ++#include "stage3b.h" ++ ++#include "lib/zt_common.h" ++#include "boot/s390.h" ++#include "boot/linux_layout.h" ++#include "boot/loaders_layout.h" ++#include "sclp.h" ++#include "error.h" ++ ++ ++static volatile struct stage3b_args __section(".loader_parms") loader_parms; ++ ++static inline void __noreturn load_psw(struct psw_t psw) ++{ ++ asm volatile("lpswe %0" : : "Q"(psw) : "cc"); ++ ++ while (1) ++ ; ++} ++ ++void __noreturn start(void) ++{ ++ volatile struct stage3b_args *args = &loader_parms; ++ volatile struct memblob *kernel = &args->kernel; ++ volatile struct memblob *cmdline = &args->cmdline; ++ volatile struct memblob *initrd = &args->initrd; ++ volatile struct psw_t psw = args->psw; ++ ++ /* set up ASCII and line-mode */ ++ sclp_setup(SCLP_LINE_ASCII_INIT); ++ ++ if (kernel->size < IMAGE_LOAD_ADDRESS) ++ panic(EINTERNAL, "Invalid kernel\n"); ++ ++ if (cmdline->size > COMMAND_LINE_SIZE) ++ panic(EINTERNAL, "Command line is too large\n"); ++ ++ /* move the kernel and cut the kernel header */ ++ memmove((void *)IMAGE_LOAD_ADDRESS, ++ (void *)(kernel->src + IMAGE_LOAD_ADDRESS), ++ kernel->size - IMAGE_LOAD_ADDRESS); ++ ++ /* move the kernel cmdline */ ++ memmove((void *)COMMAND_LINE, ++ (void *)cmdline->src, ++ cmdline->size); ++ /* the initrd does not need to be moved */ ++ ++ if (initrd->size != 0) { ++ /* copy initrd start address and size into new kernel space */ ++ *(unsigned long long *)INITRD_START = initrd->src; ++ *(unsigned long long *)INITRD_SIZE = initrd->size; ++ } ++ ++ /* disable ASCII and line-mode */ ++ sclp_setup(SCLP_DISABLE); ++ ++ /* use lpswe instead of diag308 as a I/O subsystem reset is not ++ * needed as this was already done by the diag308 subcode 10 call ++ * in stage3a ++ */ ++ load_psw(psw); ++} ++ ++void panic_notify(unsigned long UNUSED(rc)) ++{ ++} +--- /dev/null ++++ b/genprotimg/boot/stage3b.h +@@ -0,0 +1,38 @@ ++/* ++ * Main program for stage3b bootloader ++ * ++ * Copyright IBM Corp. 2020 ++ * ++ * s390-tools is free software; you can redistribute it and/or modify ++ * it under the terms of the MIT license. See LICENSE for details. ++ */ ++ ++#ifndef STAGE3B_H ++#define STAGE3B_H ++ ++#include "lib/zt_common.h" ++ ++ ++#ifndef __ASSEMBLER__ ++ ++#include ++ ++#include "boot/s390.h" ++ ++/* Must not have any padding included */ ++struct memblob { ++ uint64_t src; ++ uint64_t size; ++}; ++STATIC_ASSERT(sizeof(struct memblob) == 2 * 8) ++ ++/* Must not have any padding included */ ++struct stage3b_args { ++ struct memblob kernel; ++ struct memblob cmdline; ++ struct memblob initrd; ++ struct psw_t psw; ++}; ++STATIC_ASSERT(sizeof(struct stage3b_args) == 3 * sizeof(struct memblob) + 16) ++#endif /* __ASSEMBLER__ */ ++#endif /* STAGE3B_H */ +--- /dev/null ++++ b/genprotimg/boot/stage3b.lds +@@ -0,0 +1,87 @@ ++/* ++ * Memory layout for stage 3b ++ * ========================== ++ * ++ * General memory layout ++ * --------------------- ++ * ++ * 0x00000 - 0x01fff Lowcore ++ * 0x02000 - 0x05fff Memory allocation (heap) ++ * 0x0a000 - 0x0efff Stage3b code ++ * 0x0f000 - 0x0ffff Stack ++ */ ++ ++OUTPUT_FORMAT("elf64-s390", "elf64-s390", "elf64-s390") ++OUTPUT_ARCH(s390:64-bit) ++ ++ENTRY(_start) ++ ++__heap_size__ = 0x4000; ++__stack_size__ = 0x1000; ++ ++SECTIONS ++{ ++ . = 0x0; ++ ++ . = 0x2000; ++ __heap_start = .; ++ .heap : { ++ . = . + __heap_size__; ++ ASSERT(__heap_stop - __heap_start == __heap_size__, ++ "Heap section doesn't conform to the described memory layout"); ++ } ++ __heap_stop = .; ++ ++ . = 0xa000; ++ .text : { ++ head.o(.text.start) ++ *(.text) ++ } ++ ++ .ex_table ALIGN(16) : { ++ __ex_table_start = .; ++ *(.ex_table) ++ __ex_table_stop = .; ++ } ++ ++ .bss ALIGN(16) : { ++ __bss_start = .; ++ *(.bss) ++ __bss_stop = .; ++ } ++ ++ .rodata ALIGN(16) : { ++ *(.rodata) ++ *(.rodata.*) ++ } ++ ++ .data ALIGN(16) : { ++ *(.data) ++ . = ALIGN(16); ++ __loader_parms_start = .; ++ KEEP(*(.loader_parms)); ++ __loader_parms_end = .; ++ ASSERT(__loader_parms_end - __loader_parms_start == 3 * 16 + 16, ++ "Data size must be equal to 'sizeof(struct stage3b_args)'"); ++ } ++ ++ . = 0xf000; ++ __stack_start = .; ++ .stack : { ++ . = . + __stack_size__; ++ ASSERT(__stack_end - __stack_start == __stack_size__, ++ "Stack section doesn't conform to the described memory layout"); ++ } ++ __stack_end = .; ++ ++ /* List this explicitly as otherwise .note.gnu.build-id will be ++ * put at 0x0 */ ++ .notes : { ++ *(.note.*) ++ } ++ ++ /* Sections to be discarded */ ++ /DISCARD/ : { ++ *(.eh_frame) ++ } ++} +--- a/include/boot/ipl.h ++++ b/include/boot/ipl.h +@@ -89,6 +89,30 @@ struct ipl_pb0_ccw { + uint8_t reserved5[8]; + } __packed; + ++/* Structure must not have any padding */ ++struct ipl_pb0_pv_comp { ++ uint64_t tweak_pref; ++ uint64_t addr; ++ uint64_t len; ++}; ++STATIC_ASSERT(sizeof(struct ipl_pb0_pv_comp) == 3 * 8) ++ ++/* IPL Parameter Block 0 for PV */ ++struct ipl_pb0_pv { ++ uint32_t len; ++ uint8_t pbt; ++ uint8_t reserved1[3]; ++ uint8_t loadparm[8]; ++ uint8_t reserved2[84]; ++ uint8_t reserved3[3]; ++ uint8_t version; ++ uint8_t reserved4[4]; ++ uint32_t num_comp; ++ uint64_t pv_hdr_addr; ++ uint64_t pv_hdr_size; ++ struct ipl_pb0_pv_comp components[]; ++} __packed; ++ + struct ipl_parameter_block { + struct ipl_pl_hdr hdr; + union { +@@ -96,6 +120,7 @@ struct ipl_parameter_block { + struct ipl_pb0_common common; + struct ipl_pb0_fcp fcp; + struct ipl_pb0_ccw ccw; ++ struct ipl_pb0_pv pv; + char raw[PAGE_SIZE - sizeof(struct ipl_pl_hdr)]; + }; + } __packed __aligned(PAGE_SIZE); +--- a/include/boot/s390.h ++++ b/include/boot/s390.h +@@ -18,6 +18,12 @@ + + #define PAGE_SIZE _AC(4096, UL) + ++/* Minimum size of a stack frame in bytes */ ++#define STACK_FRAME_OVERHEAD _AC(160, U) ++ ++/* Facilities */ ++#define UNPACK_FACILITY _AC(161, U) ++ + + #ifndef __ASSEMBLER__ + +@@ -262,11 +268,17 @@ static __always_inline void __ctl_set_bi + * DIAG 308 support + */ + enum diag308_subcode { +- DIAG308_REL_HSA = 2, +- DIAG308_IPL = 3, +- DIAG308_DUMP = 4, +- DIAG308_SET = 5, +- DIAG308_STORE = 6, ++ DIAG308_REL_HSA = 2, ++ DIAG308_IPL = 3, ++ DIAG308_DUMP = 4, ++ DIAG308_SET = 5, ++ DIAG308_STORE = 6, ++ DIAG308_SET_PV = 8, ++ DIAG308_UNPACK_PV = 10, ++}; ++ ++enum diag308_rc { ++ DIAG308_RC_OK = 0x0001, + }; + + static __always_inline unsigned long diag308(unsigned long subcode, void *addr) +--- a/zipl/boot/error.h ++++ b/zipl/boot/error.h +@@ -71,4 +71,10 @@ + #define ENOTIME 0x00004605 /* The zipl time stamps do not match */ + #define ENOMSS 0x00004606 /* Could not enable MSS */ + ++/* ++ * PV error codes ++ */ ++#define ENOPV 0x00004607 /* No support for PV */ ++#define EPV 0x00004608 /* PV error */ ++ + #endif /* ERROR_H */ diff --git a/s390-tools-sles15sp2-44-genprotimg-boot-use-C-pre-processor-for-linker-scrip.patch b/s390-tools-sles15sp2-44-genprotimg-boot-use-C-pre-processor-for-linker-scrip.patch new file mode 100644 index 0000000..2d11de2 --- /dev/null +++ b/s390-tools-sles15sp2-44-genprotimg-boot-use-C-pre-processor-for-linker-scrip.patch @@ -0,0 +1,479 @@ +Subject: [PATCH] [FEAT VS1804] genprotimg: boot: use C pre-processor for linker script generation +From: Marc Hartmayer + +Summary: genprotimg: Introduce new tool for the creation of PV images +Description: genprotimg takes a kernel, host-key documents, optionally an + initrd, optionally a file with the kernel command line, and it + generates a single, loadable image file. The image consists of a + concatenation of a plain text boot loader, the encrypted + components for kernel, initrd, and cmdline, and the + integrity-protected PV header, containing metadata necessary for + running the guest in PV mode. It's possible to use this image file + as a kernel for zIPL or for a direct kernel boot using QEMU. +Upstream-ID: 2d600570df98a1d26a6f3947ae8c39bcde00b464 +Problem-ID: VS1804 + +Upstream-Description: + + genprotimg: boot: use C pre-processor for linker script generation + + Use C pre-processor for linker script generation. This allows the + usage of constants in our "linker scripts" `*.lds.S` (actually, these + are assembler files, so we can make us of the C pre-processor and its + capabilities). + + Suggested-by: Philipp Rudo + Reviewed-by: Philipp Rudo + Signed-off-by: Marc Hartmayer + Signed-off-by: Jan Höppner + + +Signed-off-by: Marc Hartmayer +--- + genprotimg/boot/.gitignore | 1 + genprotimg/boot/Makefile | 13 ++++- + genprotimg/boot/stage3a.lds | 101 ----------------------------------------- + genprotimg/boot/stage3a.lds.S | 103 ++++++++++++++++++++++++++++++++++++++++++ + genprotimg/boot/stage3b.h | 4 + + genprotimg/boot/stage3b.lds | 87 ----------------------------------- + genprotimg/boot/stage3b.lds.S | 87 +++++++++++++++++++++++++++++++++++ + 7 files changed, 207 insertions(+), 189 deletions(-) + +--- a/genprotimg/boot/.gitignore ++++ b/genprotimg/boot/.gitignore +@@ -1,3 +1,4 @@ + *.elf ++*.lds + *.bin + *.d +--- a/genprotimg/boot/Makefile ++++ b/genprotimg/boot/Makefile +@@ -39,6 +39,17 @@ all: $(FILES) + $(CC) $(ALL_CFLAGS) -c -o $@ $< + + ++# Dependencies for the .lds generation ++sources_lds_S = $(wildcard *.lds.S) ++dependencies_lds_S = $(sources_lds_s:%.lds.S=.%.lds.d) ++# Include all ".lds.d" dependency files for all make targets except for "clean" ++ifneq ($(MAKECMDGOALS),clean) ++-include $(dependencies_lds_S) ++endif ++ ++%.lds: %.lds.S Makefile ++ $(CPP) -Wp,-MD,.$@.d,-MT,$@ $(INCLUDE_PARMS) -P -C -o $@ $< ++ + # Special rules for zipl object files + $(ZIPL_OBJS_C): %.o : $(ZIPL_BOOT_DIR)/%.c + $(CC) $(ALL_CFLAGS) -c -o $@ $< +@@ -78,6 +89,6 @@ stage3b.elf: head.o stage3b.o stage3b.ld + @chmod a-x $@ + + clean: +- rm -f *.o *.elf *.bin *.map .*.d ++ rm -f *.o *.elf *.bin *.map .*.d *.lds + + .PHONY: all clean +--- a/genprotimg/boot/stage3a.lds ++++ /dev/null +@@ -1,101 +0,0 @@ +-/* +- * Memory layout for stage 3a +- * ========================== +- * +- * General memory layout +- * --------------------- +- * +- * 0x00000 - 0x01fff Lowcore +- * 0x02000 - 0x05fff Memory allocation (heap) +- * 0x0f000 - 0x0ffff Stack +- * 0x10000 - 0x10012 Jump to the "actual" stage3a code +- * 0x11000 - 0x12fff Stage3a code + arguments (offsets and lengths to the +- * actual data: IPIB and UV header) +- */ +- +-OUTPUT_FORMAT("elf64-s390", "elf64-s390", "elf64-s390") +-OUTPUT_ARCH(s390:64-bit) +- +-ENTRY(_init) +- +-__heap_size__ = 0x4000; +-__stack_size__ = 0x1000; +- +-SECTIONS +-{ +- . = 0x0; +- +- . = 0x2000; +- __heap_start = .; +- .heap : { +- . = . + __heap_size__; +- ASSERT(__heap_stop - __heap_start == __heap_size__, +- "Heap section doesn't conform to the described memory layout"); +- } +- __heap_stop = .; +- +- . = 0xf000; +- __stack_start = .; +- .stack : { +- . = . + __stack_size__; +- ASSERT(__stack_end - __stack_start == __stack_size__, +- "Stack section doesn't conform to the described memory layout"); +- } +- __stack_end = .; +- +- . = 0x10000; +- __text_init_start = .; +- .text : { +- stage3a_init.o(.text.init) +- __text_init_stop = ABSOLUTE(.); +- /* Text size of text_init must be smaller than 'PARMAREA - IMAGE_ENTRY', +- * otherwise the text data could be overwritten by the original zipl stage3 +- * boot loader */ +- ASSERT(__text_init_stop - __text_init_start < 0x400, +- "Text size must be smaller than 'PARMAREA - IMAGE_ENTRY'"); +- . = 0x1000; +- head.o(.text.start) +- *(.text) +- } +- +- .ex_table ALIGN(16) : { +- __ex_table_start = .; +- *(.ex_table) +- __ex_table_stop = .; +- } +- +- .bss ALIGN(16) : { +- __bss_start = .; +- *(.bss) +- __bss_stop = .; +- } +- +- .rodata ALIGN(16) : { +- *(.rodata) +- *(.rodata.*) +- } +- +- .data ALIGN(16) : { +- *(.data) +- . = ALIGN(16); +- /* The IPIB offset and the UV header offset and size will be +- * saved in 'loader_parms' */ +- __loader_parms_start = .; +- KEEP(*(.loader_parms)); +- __loader_parms_stop = .; +- ASSERT(__loader_parms_stop - __loader_parms_start == 3 * 8, +- "Data size must be equal to 'sizeof(struct stage3a_args)'"); +- ASSERT(ABSOLUTE(.) < 0x13000, "Data section doesn't conform to the described memory layout"); +- } +- +- /* List this explicitly as otherwise .note.gnu.build-id will be +- * put at 0x0 */ +- .notes : { +- *(.note.*) +- } +- +- /* Sections to be discarded */ +- /DISCARD/ : { +- *(.eh_frame) +- } +-} +--- /dev/null ++++ b/genprotimg/boot/stage3a.lds.S +@@ -0,0 +1,103 @@ ++/* ++ * Memory layout for stage 3a ++ * ========================== ++ * ++ * General memory layout ++ * --------------------- ++ * ++ * 0x00000 - 0x01fff Lowcore ++ * 0x02000 - 0x05fff Memory allocation (heap) ++ * 0x0f000 - 0x0ffff Stack ++ * 0x10000 - 0x10012 Jump to the "actual" stage3a code ++ * 0x11000 - 0x12fff Stage3a code + arguments (offsets and lengths to the ++ * actual data: IPIB and UV header) ++ */ ++ ++#include "stage3a.h" ++#include "common_memory_layout.h" ++ ++OUTPUT_FORMAT("elf64-s390", "elf64-s390", "elf64-s390") ++OUTPUT_ARCH(s390:64-bit) ++ ++ENTRY(_init) ++ ++SECTIONS ++{ ++ . = 0x0; ++ ++ . = HEAP_ADDRESS; ++ __heap_start = .; ++ .heap : { ++ . = . + HEAP_SIZE; ++ ASSERT(__heap_stop - __heap_start == HEAP_SIZE, ++ "Heap section doesn't conform to the described memory layout"); ++ } ++ __heap_stop = .; ++ ++ . = STACK_ADDRESS; ++ __stack_start = .; ++ .stack : { ++ . = . + STACK_SIZE; ++ ASSERT(__stack_end - __stack_start == STACK_SIZE, ++ "Stack section doesn't conform to the described memory layout"); ++ } ++ __stack_end = .; ++ ++ . = STAGE3A_INIT_ENTRY; ++ __text_init_start = .; ++ .text : { ++ stage3a_init.o(.text.init) ++ __text_init_stop = ABSOLUTE(.); ++ /* Text size of text_init must be smaller than 'PARMAREA - IMAGE_ENTRY', ++ * otherwise the text data could be overwritten by the original zipl stage3 ++ * boot loader */ ++ ASSERT(__text_init_stop - __text_init_start < PARMAREA - IMAGE_ENTRY, ++ "Text size must be smaller than 'PARMAREA - IMAGE_ENTRY'"); ++ . = 0x1000; ++ ASSERT(ABSOLUTE(.) == STAGE3A_ENTRY, ++ "Text section doesn't conform to the described memory layout"); ++ head.o(.text.start) ++ *(.text) ++ } ++ ++ .ex_table ALIGN(16) : { ++ __ex_table_start = .; ++ *(.ex_table) ++ __ex_table_stop = .; ++ } ++ ++ .bss ALIGN(16) : { ++ __bss_start = .; ++ *(.bss) ++ __bss_stop = .; ++ } ++ ++ .rodata ALIGN(16) : { ++ *(.rodata) ++ *(.rodata.*) ++ } ++ ++ .data ALIGN(16) : { ++ *(.data) ++ . = ALIGN(16); ++ /* The IPIB offset and the UV header offset and size will be ++ * saved in 'loader_parms' */ ++ __loader_parms_start = .; ++ KEEP(*(.loader_parms)); ++ __loader_parms_stop = .; ++ ASSERT(__loader_parms_stop - __loader_parms_start == 3 * 8, ++ "Data size must be equal to 'sizeof(struct stage3a_args)'"); ++ ASSERT(ABSOLUTE(.) < 0x13000, "Data section doesn't conform to the described memory layout"); ++ } ++ ++ /* List this explicitly as otherwise .note.gnu.build-id will be ++ * put at 0x0 */ ++ .notes : { ++ *(.note.*) ++ } ++ ++ /* Sections to be discarded */ ++ /DISCARD/ : { ++ *(.eh_frame) ++ } ++} +--- a/genprotimg/boot/stage3b.h ++++ b/genprotimg/boot/stage3b.h +@@ -11,6 +11,10 @@ + #define STAGE3B_H + + #include "lib/zt_common.h" ++#include "boot/loaders_layout.h" ++ ++#define STAGE3B_ENTRY STAGE3_ENTRY ++#define STAGE3B_LOAD_ADDRESS STAGE3B_ENTRY + + + #ifndef __ASSEMBLER__ +--- a/genprotimg/boot/stage3b.lds ++++ /dev/null +@@ -1,87 +0,0 @@ +-/* +- * Memory layout for stage 3b +- * ========================== +- * +- * General memory layout +- * --------------------- +- * +- * 0x00000 - 0x01fff Lowcore +- * 0x02000 - 0x05fff Memory allocation (heap) +- * 0x0a000 - 0x0efff Stage3b code +- * 0x0f000 - 0x0ffff Stack +- */ +- +-OUTPUT_FORMAT("elf64-s390", "elf64-s390", "elf64-s390") +-OUTPUT_ARCH(s390:64-bit) +- +-ENTRY(_start) +- +-__heap_size__ = 0x4000; +-__stack_size__ = 0x1000; +- +-SECTIONS +-{ +- . = 0x0; +- +- . = 0x2000; +- __heap_start = .; +- .heap : { +- . = . + __heap_size__; +- ASSERT(__heap_stop - __heap_start == __heap_size__, +- "Heap section doesn't conform to the described memory layout"); +- } +- __heap_stop = .; +- +- . = 0xa000; +- .text : { +- head.o(.text.start) +- *(.text) +- } +- +- .ex_table ALIGN(16) : { +- __ex_table_start = .; +- *(.ex_table) +- __ex_table_stop = .; +- } +- +- .bss ALIGN(16) : { +- __bss_start = .; +- *(.bss) +- __bss_stop = .; +- } +- +- .rodata ALIGN(16) : { +- *(.rodata) +- *(.rodata.*) +- } +- +- .data ALIGN(16) : { +- *(.data) +- . = ALIGN(16); +- __loader_parms_start = .; +- KEEP(*(.loader_parms)); +- __loader_parms_end = .; +- ASSERT(__loader_parms_end - __loader_parms_start == 3 * 16 + 16, +- "Data size must be equal to 'sizeof(struct stage3b_args)'"); +- } +- +- . = 0xf000; +- __stack_start = .; +- .stack : { +- . = . + __stack_size__; +- ASSERT(__stack_end - __stack_start == __stack_size__, +- "Stack section doesn't conform to the described memory layout"); +- } +- __stack_end = .; +- +- /* List this explicitly as otherwise .note.gnu.build-id will be +- * put at 0x0 */ +- .notes : { +- *(.note.*) +- } +- +- /* Sections to be discarded */ +- /DISCARD/ : { +- *(.eh_frame) +- } +-} +--- /dev/null ++++ b/genprotimg/boot/stage3b.lds.S +@@ -0,0 +1,87 @@ ++/* ++ * Memory layout for stage 3b ++ * ========================== ++ * ++ * General memory layout ++ * --------------------- ++ * ++ * 0x00000 - 0x01fff Lowcore ++ * 0x02000 - 0x05fff Memory allocation (heap) ++ * 0x0a000 - 0x0efff Stage3b code ++ * 0x0f000 - 0x0ffff Stack ++ */ ++ ++#include "stage3b.h" ++#include "common_memory_layout.h" ++ ++OUTPUT_FORMAT("elf64-s390", "elf64-s390", "elf64-s390") ++OUTPUT_ARCH(s390:64-bit) ++ ++ENTRY(_start) ++ ++SECTIONS ++{ ++ . = 0x0; ++ ++ . = HEAP_ADDRESS; ++ __heap_start = .; ++ .heap : { ++ . = . + HEAP_SIZE; ++ ASSERT(__heap_stop - __heap_start == HEAP_SIZE, ++ "Heap section doesn't conform to the described memory layout"); ++ } ++ __heap_stop = .; ++ ++ . = STAGE3B_ENTRY; ++ .text : { ++ head.o(.text.start) ++ *(.text) ++ } ++ ++ .ex_table ALIGN(16) : { ++ __ex_table_start = .; ++ *(.ex_table) ++ __ex_table_stop = .; ++ } ++ ++ .bss ALIGN(16) : { ++ __bss_start = .; ++ *(.bss) ++ __bss_stop = .; ++ } ++ ++ .rodata ALIGN(16) : { ++ *(.rodata) ++ *(.rodata.*) ++ } ++ ++ .data ALIGN(16) : { ++ *(.data) ++ . = ALIGN(16); ++ __loader_parms_start = .; ++ KEEP(*(.loader_parms)); ++ __loader_parms_end = .; ++ ASSERT(__loader_parms_end - __loader_parms_start == 3 * 16 + 16, ++ "Data size must be equal to 'sizeof(struct stage3b_args)'"); ++ } ++ ++ . = STACK_ADDRESS; ++ __stack_start = .; ++ .stack : { ++ . = . + STACK_SIZE; ++ ASSERT(__stack_end - __stack_start == STACK_SIZE, ++ "Stack section doesn't conform to the described memory layout"); ++ } ++ __stack_end = .; ++ ++ /* List this explicitly as otherwise .note.gnu.build-id will be ++ * put at 0x0 */ ++ .notes : { ++ *(.note.*) ++ } ++ ++ /* Sections to be discarded */ ++ /DISCARD/ : { ++ *(.eh_frame) ++ } ++} diff --git a/s390-tools-sles15sp2-45-genprotimg-add-relocator-for-stage3b.patch b/s390-tools-sles15sp2-45-genprotimg-add-relocator-for-stage3b.patch new file mode 100644 index 0000000..bc68a2b --- /dev/null +++ b/s390-tools-sles15sp2-45-genprotimg-add-relocator-for-stage3b.patch @@ -0,0 +1,120 @@ +Subject: [PATCH] [FEAT VS1804] genprotimg: add relocator for stage3b +From: Marc Hartmayer + +Summary: genprotimg: Introduce new tool for the creation of PV images +Description: genprotimg takes a kernel, host-key documents, optionally an + initrd, optionally a file with the kernel command line, and it + generates a single, loadable image file. The image consists of a + concatenation of a plain text boot loader, the encrypted + components for kernel, initrd, and cmdline, and the + integrity-protected PV header, containing metadata necessary for + running the guest in PV mode. It's possible to use this image file + as a kernel for zIPL or for a direct kernel boot using QEMU. +Upstream-ID: d2f8f972cff7aacbef8e72577af70dbf59ba3ead +Problem-ID: VS1804 + +Upstream-Description: + + genprotimg: add relocator for stage3b + + Add support for the placement of the stage3b loader at other addresses + than 0xa000. For this add a position independent relocator that first + copies the original stage3b code to the memory location 0xa000 and + then starts it. + + Reviewed-by: Philipp Rudo + Signed-off-by: Marc Hartmayer + Signed-off-by: Jan Höppner + + +Signed-off-by: Marc Hartmayer +--- + genprotimg/boot/Makefile | 5 +++ + genprotimg/boot/stage3b_reloc.S | 53 ++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 57 insertions(+), 1 deletion(-) + +--- a/genprotimg/boot/Makefile ++++ b/genprotimg/boot/Makefile +@@ -17,7 +17,7 @@ ALL_CFLAGS := $(NO_PIE_CFLAGS) -Os -g \ + -mstack-size=4096 -mstack-guard=128 -msoft-float \ + -Wall -Wformat-security -Wextra -Werror + +-FILES := stage3a.bin stage3b.bin ++FILES := stage3a.bin stage3b.bin stage3b_reloc.bin + + ZIPL_SRCS_C := libc.c ebcdic.c ebcdic_conv.c sclp.c + ZIPL_SRCS_ASM := entry.S +@@ -66,14 +66,17 @@ ifneq ($(MAKECMDGOALS),clean) + -include $(dependencies_zipl_c) + endif + ++stage3b_reloc.o: stage3b.bin + + stage3a.elf: head.o stage3a_init.o stage3a.o stage3a.lds $(ZIPL_OBJS) + stage3b.elf: head.o stage3b.o stage3b.lds $(ZIPL_OBJS) ++stage3b_reloc.elf: + + %.elf: %.o + case $* in \ + stage3a) SFLAGS="$(NO_PIE_LINKFLAGS) -nostdlib -Wl,-T,stage3a.lds";; \ + stage3b) SFLAGS="$(NO_PIE_LINKFLAGS) -nostdlib -Wl,-T,stage3b.lds";; \ ++ stage3b_reloc) SFLAGS="$(NO_PIE_LINKFLAGS) -nostdlib -Wl,-estage3b_reloc_start,-Ttext,0";; \ + esac; \ + $(LINK) $$SFLAGS -m64 $(filter %.o, $^) -o $@ + @chmod a-x $@ +--- /dev/null ++++ b/genprotimg/boot/stage3b_reloc.S +@@ -0,0 +1,53 @@ ++/* ++ * Relocator code for stage 3b boot loader ++ * ++ * Copyright IBM Corp. 2020 ++ * ++ * s390-tools is free software; you can redistribute it and/or modify ++ * it under the terms of the MIT license. See LICENSE for details. ++ */ ++ ++#include "stage3b.h" ++#include "boot/sigp.h" ++ ++.macro MEMCPY dst,src,len ++ lgr %r0, \dst ++ lgr %r1, \len ++ lgr %r2, \src ++ lgr %r3, \len ++ ++20: mvcle %r0, %r2, 0 ++ jo 20b ++.endm ++ ++.org 0x0 ++.section .text.start ++.globl stage3b_reloc_start ++stage3b_reloc_start: ++ /* Might be called after a diag308 so better set ++ * architecture and addressing mode ++ */ ++ lhi %r1, 1 ++ sigp %r1, %r0, SIGP_SET_ARCHITECTURE ++ sam64 ++ ++.copy_stage3b: ++ /* Location of stage3b in memory */ ++ larl %r8, stage3b_start ++ ++ /* Destination for stage3b */ ++ lgfi %r9, STAGE3B_LOAD_ADDRESS ++ ++ /* Size of stage3b */ ++ lghi %r11, stage3b_end - stage3b_start ++ ++ /* Copy the stage3b loader to address STAGE3B_LOAD_ADDRESS */ ++ MEMCPY %r9, %r8, %r11 ++ ++ /* Branch to STAGE3B_ENTRY */ ++ lgfi %r9, STAGE3B_ENTRY ++ br %r9 ++stage3b_start: ++ .incbin "stage3b.bin" ++stage3b_end: ++.previous diff --git a/s390-tools-sles15sp2-46-README.md-remove-useless-empty-line.patch b/s390-tools-sles15sp2-46-README.md-remove-useless-empty-line.patch new file mode 100644 index 0000000..b8c3afd --- /dev/null +++ b/s390-tools-sles15sp2-46-README.md-remove-useless-empty-line.patch @@ -0,0 +1,38 @@ +Subject: [PATCH] [FEAT VS1804] README.md: remove useless empty line +From: Marc Hartmayer + +Summary: genprotimg: Introduce new tool for the creation of PV images +Description: genprotimg takes a kernel, host-key documents, optionally an + initrd, optionally a file with the kernel command line, and it + generates a single, loadable image file. The image consists of a + concatenation of a plain text boot loader, the encrypted + components for kernel, initrd, and cmdline, and the + integrity-protected PV header, containing metadata necessary for + running the guest in PV mode. It's possible to use this image file + as a kernel for zIPL or for a direct kernel boot using QEMU. +Upstream-ID: b06af6026f08d67339a109ba7457373ab82d3248 +Problem-ID: VS1804 + +Upstream-Description: + + README.md: remove useless empty line + + Remove useless empty line. + + Reviewed-by: Jan Höppner + Signed-off-by: Marc Hartmayer + Signed-off-by: Jan Höppner + + +Signed-off-by: Marc Hartmayer +--- + README.md | 1 - + 1 file changed, 1 deletion(-) + +--- a/README.md ++++ b/README.md +@@ -1,4 +1,3 @@ +- + s390-tools + ========== + diff --git a/s390-tools-sles15sp2-47-include-boot-s390.h-add-guard-for-struct-__vector128.patch b/s390-tools-sles15sp2-47-include-boot-s390.h-add-guard-for-struct-__vector128.patch new file mode 100644 index 0000000..114e0cc --- /dev/null +++ b/s390-tools-sles15sp2-47-include-boot-s390.h-add-guard-for-struct-__vector128.patch @@ -0,0 +1,54 @@ +Subject: [PATCH] [FEAT VS1804] include/boot/s390.h: add guard for `struct __vector128` +From: Marc Hartmayer + +Summary: genprotimg: Introduce new tool for the creation of PV images +Description: genprotimg takes a kernel, host-key documents, optionally an + initrd, optionally a file with the kernel command line, and it + generates a single, loadable image file. The image consists of a + concatenation of a plain text boot loader, the encrypted + components for kernel, initrd, and cmdline, and the + integrity-protected PV header, containing metadata necessary for + running the guest in PV mode. It's possible to use this image file + as a kernel for zIPL or for a direct kernel boot using QEMU. +Upstream-ID: 11bdab26297e508fdab29f9457094eedf681de53 +Problem-ID: VS1804 + +Upstream-Description: + + include/boot/s390.h: add guard for `struct __vector128` + + `linux/asm/types.h` also defines the struct `__vector128` so in order + to avoid definition conflicts add the macro guard _S390_TYPES_H, which + is defined in `linux/asm/types`. `linux/asm/types.h` is included by + glib2, which is used by the PV tooling. + + Reviewed-by: Jan Höppner + Signed-off-by: Marc Hartmayer + Signed-off-by: Jan Höppner + + +Signed-off-by: Marc Hartmayer +--- + include/boot/s390.h | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/include/boot/s390.h ++++ b/include/boot/s390.h +@@ -358,12 +358,17 @@ static __always_inline int is_zvm(void) + return cpuid.version == 0xff; + } + ++/* To avoid conflicts add a macro guard since __vector128 is also ++ * defined in 'linux/asm/types.h'. ++ */ ++#ifndef _S390_TYPES_H + /* + * Vector register definition + */ + typedef struct { + uint32_t u[4]; + } __vector128; ++#endif + + /* + * Save vector registers diff --git a/s390-tools-sles15sp2-48-genprotimg-introduce-new-tool-for-the-creation-of-PV.patch b/s390-tools-sles15sp2-48-genprotimg-introduce-new-tool-for-the-creation-of-PV.patch new file mode 100644 index 0000000..20241da --- /dev/null +++ b/s390-tools-sles15sp2-48-genprotimg-introduce-new-tool-for-the-creation-of-PV.patch @@ -0,0 +1,5198 @@ +Subject: [PATCH] [FEAT VS1804] genprotimg: introduce new tool for the creation of PV images +From: Marc Hartmayer + +Summary: genprotimg: Introduce new tool for the creation of PV images +Description: genprotimg takes a kernel, host-key documents, optionally an + initrd, optionally a file with the kernel command line, and it + generates a single, loadable image file. The image consists of a + concatenation of a plain text boot loader, the encrypted + components for kernel, initrd, and cmdline, and the + integrity-protected PV header, containing metadata necessary for + running the guest in PV mode. It's possible to use this image file + as a kernel for zIPL or for a direct kernel boot using QEMU. +Upstream-ID: 65b9fc442c1a4ff24583171e714e5fdb1e92c8fd +Problem-ID: VS1804 + +Upstream-Description: + + genprotimg: introduce new tool for the creation of PV images + + Protected VMs (PVM) are KVM VMs, where KVM can't access the VM's state + like guest memory and guest registers anymore. Instead the PVMs are + mostly managed by a new entity called Ultravisor (UV), which provides + an API, so KVM and the PV can request management actions. + + PVMs are encrypted at rest and protected from hypervisor access while + running. They switch from a normal operation into protected mode, so + we can still use the standard boot process to load an encrypted image + and then move it into protected mode. + + This commit adds the tool 'genprotimg'. It takes a kernel, key files, + optionally an initrd, optionally a file with the kernel command line, + and it generates a single, loadable image file. The image consists of + a concatenation of a plain text boot loader, the encrypted components + for kernel, initrd, and cmdline, and the integrity-protected PV + header, containing metadata necessary for running the guest in PV + mode. + + It's possible to use this image file as a kernel for zipl or for a + direct kernel boot using QEMU. + + Reviewed-by: Bjoern Walk + Acked-by: Patrick Steuer + Reviewed-by: Claudio Imbrenda + Reviewed-by: Jan Höppner + Signed-off-by: Marc Hartmayer + Signed-off-by: Jan Höppner + + +Signed-off-by: Marc Hartmayer +--- + Makefile | 4 + README.md | 6 + genprotimg/.gitignore | 5 + genprotimg/Makefile | 26 + + genprotimg/README.md | 101 ++++ + genprotimg/man/Makefile | 12 + genprotimg/man/genprotimg.8 | 97 +++ + genprotimg/src/Makefile | 101 ++++ + genprotimg/src/common.h | 39 + + genprotimg/src/genprotimg.c | 181 +++++++ + genprotimg/src/include/pv_crypto_def.h | 25 + + genprotimg/src/include/pv_hdr_def.h | 84 +++ + genprotimg/src/pv/pv_args.c | 405 ++++++++++++++++ + genprotimg/src/pv/pv_args.h | 53 ++ + genprotimg/src/pv/pv_comp.c | 446 +++++++++++++++++ + genprotimg/src/pv/pv_comp.h | 78 +++ + genprotimg/src/pv/pv_comps.c | 252 ++++++++++ + genprotimg/src/pv/pv_comps.h | 42 + + genprotimg/src/pv/pv_error.c | 37 + + genprotimg/src/pv/pv_error.h | 62 ++ + genprotimg/src/pv/pv_hdr.c | 293 +++++++++++ + genprotimg/src/pv/pv_hdr.h | 36 + + genprotimg/src/pv/pv_image.c | 820 +++++++++++++++++++++++++++++++++ + genprotimg/src/pv/pv_image.h | 68 ++ + genprotimg/src/pv/pv_ipib.c | 128 +++++ + genprotimg/src/pv/pv_ipib.h | 27 + + genprotimg/src/pv/pv_opt_item.c | 26 + + genprotimg/src/pv/pv_opt_item.h | 20 + genprotimg/src/pv/pv_stage3.c | 164 ++++++ + genprotimg/src/pv/pv_stage3.h | 30 + + genprotimg/src/utils/align.h | 24 + genprotimg/src/utils/buffer.c | 69 ++ + genprotimg/src/utils/buffer.h | 31 + + genprotimg/src/utils/crypto.c | 798 ++++++++++++++++++++++++++++++++ + genprotimg/src/utils/crypto.h | 104 ++++ + genprotimg/src/utils/file_utils.c | 234 +++++++++ + genprotimg/src/utils/file_utils.h | 34 + + include/boot/ipl.h | 5 + 38 files changed, 4965 insertions(+), 2 deletions(-) + +--- a/Makefile ++++ b/Makefile +@@ -8,7 +8,9 @@ TOOL_DIRS = zipl zdump fdasd dasdfmt das + tape390 osasnmpd qetharp ip_watcher qethconf scripts zconf \ + vmconvert vmcp man mon_tools dasdinfo vmur cpuplugd ipl_tools \ + ziomon iucvterm hyptop cmsfs-fuse qethqoat zfcpdump zdsfs cpumf \ +- systemd hmcdrvfs cpacfstats zdev dump2tar zkey netboot etc zpcictl ++ systemd hmcdrvfs cpacfstats zdev dump2tar zkey netboot etc zpcictl \ ++ genprotimg ++ + SUB_DIRS = $(LIB_DIRS) $(TOOL_DIRS) + + all: $(TOOL_DIRS) +--- a/README.md ++++ b/README.md +@@ -30,6 +30,9 @@ Package contents + * dasdinfo: + Display unique DASD ID, either UID or volser. + ++ * genprotimg: ++ Create a protected virtualization image. ++ + * udev rules: + - 59-dasd.rules: rules for unique DASD device nodes created in /dev/disk/. + - 57-osasnmpd.rules: udev rules for osasnmpd. +@@ -264,9 +267,10 @@ build options: + | pfm | `HAVE_PFM` | cpacfstats | + | net-snmp | `HAVE_SNMP` | osasnmpd | + | glibc-static | `HAVE_LIBC_STATIC` | zfcpdump | +-| openssl | `HAVE_OPENSSL` | zkey | ++| openssl | `HAVE_OPENSSL` | genprotimg,zkey | + | cryptsetup | `HAVE_CRYPTSETUP2` | zkey-cryptsetup | + | json-c | `HAVE_JSONC` | zkey-cryptsetup | ++| glib2 | `HAVE_GLIB2` | genprotimg | + + This table lists additional build or install options: + +--- /dev/null ++++ b/genprotimg/.gitignore +@@ -0,0 +1,5 @@ ++tags ++compile_commands.json ++src/.check-dep-genprotimg ++src/.detect-openssl.dep.c ++src/genprotimg +--- /dev/null ++++ b/genprotimg/Makefile +@@ -0,0 +1,26 @@ ++# Common definitions ++include ../common.mak ++ ++.DEFAULT_GOAL := all ++ ++PKGDATADIR := "$(DESTDIR)$(TOOLS_DATADIR)/genprotimg" ++TESTS := ++SUBDIRS := boot src man ++RECURSIVE_TARGETS := all-recursive install-recursive clean-recursive ++ ++all: all-recursive ++ ++install: all install-recursive ++ $(INSTALL) -d -m 755 "$(PKGDATADIR)" ++ $(INSTALL) -g $(GROUP) -o $(OWNER) -m 644 boot/stage3a.bin "$(PKGDATADIR)" ++ $(INSTALL) -g $(GROUP) -o $(OWNER) -m 644 boot/stage3b_reloc.bin "$(PKGDATADIR)" ++ ++clean: clean-recursive ++ ++$(RECURSIVE_TARGETS): ++ @target=`echo $@ |sed s/-recursive//`; \ ++ for d in $(SUBDIRS); do \ ++ $(MAKE) -C $$d $$target; \ ++ done ++ ++.PHONY: all install clean $(RECURSIVE_TARGETS) +--- /dev/null ++++ b/genprotimg/README.md +@@ -0,0 +1,101 @@ ++# genprotimg ++ ++`genprotimg` takes a kernel, key files, optionally an initrd image, ++optionally a file containing the kernel command line parameters, and ++generates a single, bootable image file. The generated image file ++consists of a concatenation of a plain text boot loader, the encrypted ++components for kernel, initrd, kernel command line, and the ++integrity-protected PV header, containing the metadata necessary for ++running the guest in protected mode. See [Memory Layout](#memory-layout) ++for details about the internal structure of the created image. ++ ++It is possible to use the generated image as a kernel for zipl or for ++a direct kernel boot using QEMU. ++ ++## Getting started ++ ++If all dependencies are met a simple `make` call in the source tree ++should be enough for building `genprotimg`. ++ ++## Details ++ ++The main idea of `genprotimg` is: ++ ++1. read in all keys, IVs, and other information needed for the ++ encryption of the components and the generation of the PV header ++2. add stub stage3a (so we can calculate the memory addresses) ++3. add components: prepare the components (alignment and encryption) ++ and add them to the memory layout ++4. build and add stage3b: generate the stage3b and add it to the memory layout ++5. generate the PV header: generate the hashes (pld, ald, and tld) of ++ the components and create the PV header and IPIB ++6. parameterize the stub stage3a: uses the IPIB and PV header ++7. write the final image to the specified output path ++ ++### Boot Loader ++ ++The boot loader consists of two parts: ++ ++1. stage3a boot loader (cleartext), this loader is responsible for the ++ transition into the protected mode by doing diag308 subcode 8 and ++ 10 calls. ++2. stage3b boot loader (encrypted), this loader is very similar to the ++ normal zipl stage3 boot loader. It will be loaded by the Ultravisor ++ after the successful transition into protected mode. Like the zipl ++ stage3 boot loader it moves the kernel and patches in the values ++ for initrd and parmline. ++ ++The loaders have the following constraints: ++ ++1. It must be possible to place stage3a and stage3b at a location ++ greater than 0x10000 because the zipl stage3 loader zeroes out ++ everything at addresses lower than 0x10000 of the image. ++2. As the stage3 loader of zipl assumes that the passed kernel image ++ looks like a normal kernel image, the zipl stage3 loader modifies the ++ content at the memory area 0x10400 - 0x10800, therefore we leave this ++ area unused in our stage3a loader. ++3. The default entry address used by the zipl stage3 loader is 0x10000 ++ so we add a simple branch to 0x11000 at 0x10000 so the zipl stage3 ++ loader can modify the area 0x10400 - 0x10800 without affecting the ++ stage3a loader. ++ ++#### Detail about stage3b ++ ++The stage3b.bin is linked at address 0x9000, therefore it will not ++work at another address. The relocation support for the stage3b ++loader, so that it can be placed at addresses != 0x9000, is added in ++the loader with the name stage3b_reloc.bin. By default, if we're ++talking about stage3b we refer to stage3b_reloc.bin. ++ ++### Memory Layout ++ ++The memory layout of the bootable file looks like: ++ +++-----------------------+-----------+------------------------+ ++|Start |End |Use | +++=======================+===========+========================+ ++|0 |0x7 |Short PSW, starting | ++| | |instruction at 0x11000 | +++-----------------------+-----------+------------------------+ ++|0x10000 |0x10012 |Branch to 0x11000 | +++-----------------------+-----------+------------------------+ ++|0x10013 |0x10fff |Left intentionally | ++| | |unused | +++-----------------------+-----------+------------------------+ ++|0x11000 |0x12fff |Stage3a | +++-----------------------+-----------+------------------------+ ++|0x13000 |0x13fff |IPIB used as argument | ++| | |for the diag308 call | +++-----------------------+-----------+------------------------+ ++|0x14000 |0x1[45]fff |UV header used for the | ++| | |diag308 call (size can | ++| | |be either 1 or 2 pages) | +++-----------------------+-----------+------------------------+ ++|NEXT_PAGE_ALIGNED_ADDR | |Encrypted Kernel | +++-----------------------+-----------+------------------------+ ++|NEXT_PAGE_ALIGNED_ADDR | |Encrypted Cmdline | +++-----------------------+-----------+------------------------+ ++|NEXT_PAGE_ALIGNED_ADDR | |Encrypted Initrd | +++-----------------------+-----------+------------------------+ ++|NEXT_PAGE_ALIGNED_ADDR | |Encrypted Stage3b_reloc | +++-----------------------+-----------+------------------------+ +--- /dev/null ++++ b/genprotimg/man/Makefile +@@ -0,0 +1,12 @@ ++# Common definitions ++include ../../common.mak ++ ++all: ++ ++install: ++ $(INSTALL) -d -m 755 $(DESTDIR)$(MANDIR)/man8 ++ $(INSTALL) -m 644 -c genprotimg.8 $(DESTDIR)$(MANDIR)/man8 ++ ++clean: ++ ++.PHONY: all install clean +--- /dev/null ++++ b/genprotimg/man/genprotimg.8 +@@ -0,0 +1,97 @@ ++.\" Copyright 2020 IBM Corp. ++.\" s390-tools is free software; you can redistribute it and/or modify ++.\" it under the terms of the MIT license. See LICENSE for details. ++.\" ++.TH GENPROTIMG 8 "March 2020" "s390-tools" ++.SH NAME ++genprotimg \- Create a protected virtualization image ++ ++.SH SYNOPSIS ++.SY ++.B genprotimg ++\fB\-k\fR \fIHOST_KEY_DOCUMENT\fR... ++\fB\-i\fR \fIVMLINUZ\fR ++[\fB\-r\fR \fIRAMDISK\fR] ++[\fB\-p\fR \fIPARMFILE\fR] ++\fB\-o\fR \fIOUTFILE\fR ++[\fIOPTION\fR]... ++.YS ++ ++.SH DESCRIPTION ++.PP ++Use \fBgenprotimg\fR to generate a single bootable image file with ++encrypted and integrity-protected parts. The command requires a kernel ++image, a host-key document, and an output file name. Optionally, ++specify an initial RAM filesystem, and a file containing the kernel ++parameters. Should special circumstances require it, you can ++optionally specify your own keys for the encryption by using the ++experimental options. In the resulting image file, a plain text boot ++loader, the encrypted components for kernel, initial RAM disk, kernel ++parameters, and the encrypted and integrity-protected header are ++concatenated. The header contains metadata necessary for running the ++guest in protected mode. ++.PP ++Use this image file as a kernel image for zipl or for a direct kernel ++boot using QEMU. ++ ++.SH OPTIONS ++.TP ++\fB\-h\fR, \fB\-\-help\fR ++Prints usage information, then exits. ++.TP ++\fB\-\-help-experimental\fR ++Prints experimental usage information, then exits. ++.TP ++\fB\-\-help-all\fR ++Prints all usage information, then exits. ++.TP ++\fB\-V\fR, \fB\-\-verbose\fR ++Provides more detailed output. ++.TP ++\fB\-k\fR, \fB\-\-host-key-document\fR=\fI\,HOST_KEY_DOCUMENT\/\fR ++Specifies a host-key document. At least one is required. Specify this ++option multiple times to enable the image to run on more than one ++host. ++.TP ++\fB\-o\fR, \fB\-\-output\fR=\fI\,OUTPUT_FILE\/\fR ++Specifies the output file. Required. ++.TP ++\fB\-i\fR, \fB\-\-image\fR=\fI\,VMLINUZ\/\fR ++Specifies the Linux kernel image file. Required. ++.TP ++\fB\-r\fR, \fB\-\-ramdisk\fR=\fI\,RAMDISK\/\fR ++Specifies the RAM disk image. Optional. ++.TP ++\fB\-p\fR, \fB\-\-parmfile\fR=\fI\,PARMFILE\/\fR ++Specifies the kernel command line stored in \fI\,PARMFILE\/\fR. Optional. ++.TP ++\fB\-\-no-verify\fR ++Do not require the host-key documents to be valid. For testing ++purposes, do not use for a production image. Optional. ++.TP ++\fB\-v\fR, \fB\-\-version\fR ++Prints version information, then exits. ++ ++.SH EXAMPLE ++.PP ++Generate a protected virtualization image in ++\fI\,/boot/vmlinuz.pv\/\fR, using the kernel file \fI\,vmlinuz\/\fR, ++the initrd in \fI\,initramfs\/\fR, the kernel parameters contained in ++\fI\,parmfile\/\fR, and the host-key document in \fI\,host_key.crt\/\fR: ++.PP ++.Vb 1 ++.EX ++\& genprotimg \-i \fI\,vmlinuz\/\fR \-r \fI\,initramfs\/\fR \-p \fI\,parmfile\/\fR \-k \fI\,host_key.crt\/\fR \-o \fI\,/boot/vmlinuz.pv\/\fR ++.EE ++.Ve ++.PP ++ ++.SH NOTES ++.IP "1." 4 ++An ELF file cannot be used as a Linux kernel image. ++.IP "2." 4 ++Remember to re-run \fBzipl\fR after updating a protected ++virtualization image. ++ ++.SH SEE ALSO ++\&\fBzipl\fR\|(5), \fBqemu\fR\|(1) +--- /dev/null ++++ b/genprotimg/src/Makefile +@@ -0,0 +1,101 @@ ++# Common definitions ++include ../../common.mak ++ ++bin_PROGRAM = genprotimg ++ ++PKGDATADIR ?= "$(DESTDIR)$(TOOLS_DATADIR)/genprotimg" ++SRC_DIR := $(dir $(realpath $(firstword $(MAKEFILE_LIST)))) ++TOP_SRCDIR := $(SRC_DIR)/../ ++ROOT_DIR = $(TOP_SRC_DIR)/../../ ++ZIPL_DIR = $(ROOT_DIR)/zipl ++LOADER_DIR = $(TOP_SRCDIR)/boot ++ ++INCLUDE_PATHS = "$(SRC_DIR)" "$(TOP_SRCDIR)" "$(ROOTDIR)/include" ++INCLUDE_PARMS = $(addprefix -I,$(INCLUDE_PATHS)) ++ ++WARNINGS := -Wall -Wextra -Wshadow \ ++ -Wcast-align -Wwrite-strings -Wmissing-prototypes \ ++ -Wmissing-declarations -Wredundant-decls -Wnested-externs -Winline \ ++ -Wno-long-long -Wuninitialized -Wconversion -Wstrict-prototypes \ ++ -Wpointer-arith -Werror \ ++ $(NULL) ++ ++$(bin_PROGRAM)_SRCS := $(bin_PROGRAM).c pv/pv_stage3.c pv/pv_image.c \ ++ pv/pv_comp.c pv/pv_hdr.c pv/pv_ipib.c utils/crypto.c utils/file_utils.c \ ++ pv/pv_args.c utils/buffer.c pv/pv_comps.c pv/pv_error.c \ ++ pv/pv_opt_item.c \ ++ $(NULL) ++$(bin_PROGRAM)_OBJS := $($(bin_PROGRAM)_SRCS:.c=.o) ++ ++ALL_CFLAGS += -std=gnu11 -DPKGDATADIR=$(PKGDATADIR) \ ++ $(GLIB2_CFLAGS) $(LIBCRYPTO_CFLAGS) \ ++ $(WARNINGS) \ ++ $(NULL) ++ALL_CPPFLAGS += $(INCLUDE_PARMS) ++LDLIBS += $(GLIB2_LIBS) $(LIBCRYPTO_LIBS) ++ ++ ++ifneq ($(shell sh -c 'command -v pkg-config'),) ++GLIB2_CFLAGS := $(shell pkg-config --silence-errors --cflags glib-2.0) ++GLIB2_LIBS := $(shell pkg-config --silence-errors --libs glib-2.0) ++LIBCRYPTO_CFLAGS := $(shell pkg-config --silence-errors --cflags libcrypto) ++LIBCRYPTO_LIBS := $(shell pkg-config --silence-errors --libs libcrypto) ++else ++GLIB2_CFLAGS := -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include ++GLIB2_LIBS := -lglib-2.0 ++LIBCRYPTO_CFLAGS := ++LIBCRYPTO_LIBS := -lcrypto ++endif ++ ++BUILD_TARGETS := skip-$(bin_PROGRAM) ++INSTALL_TARGETS := skip-$(bin_PROGRAM) ++ifneq (${HAVE_OPENSSL},0) ++ifneq (${HAVE_GLIB2},0) ++BUILD_TARGETS := $(bin_PROGRAM) ++INSTALL_TARGETS := install-$(bin_PROGRAM) ++endif ++endif ++ ++all: $(BUILD_TARGETS) ++ ++install: $(INSTALL_TARGETS) ++ ++$(bin_PROGRAM): $($(bin_PROGRAM)_OBJS) ++ ++skip-$(bin_PROGRAM): ++ echo " SKIP $(bin_PROGRAM) due to unresolved dependencies" ++ ++install-$(bin_PROGRAM): $(bin_PROGRAM) ++ $(INSTALL) -d -m 755 $(DESTDIR)$(USRBINDIR) ++ $(INSTALL) -c $^ $(DESTDIR)$(USRBINDIR) ++ ++clean: ++ $(RM) -f $($(bin_PROGRAM)_OBJS) $(bin_PROGRAM) .check-dep-$(bin_PROGRAM) .detect-openssl.dep.c ++ ++.PHONY: all install clean skip-$(bin_PROGRAM) install-$(bin_PROGRAM) ++ ++$($(bin_PROGRAM)_OBJS): .check-dep-$(bin_PROGRAM) ++ ++.detect-openssl.dep.c: ++ echo "#include " > $@ ++ echo "#if OPENSSL_VERSION_NUMBER < 0x10100000L" >> $@ ++ echo " #error openssl version 1.1.0 is required" >> $@ ++ echo "#endif" >> $@ ++ echo "static void __attribute__((unused)) test(void) {" >> $@ ++ echo " EVP_MD_CTX *ctx = EVP_MD_CTX_new();" >> $@ ++ echo " EVP_MD_CTX_free(ctx);" >> $@ ++ echo "}" >> $@ ++ ++.check-dep-$(bin_PROGRAM): .detect-openssl.dep.c ++ $(call check_dep, \ ++ "$(bin_PROGRAM)", \ ++ "glib.h", \ ++ "glib2-devel / libglib2.0-dev", \ ++ "HAVE_GLIB2=0") ++ $(call check_dep, \ ++ "$(bin_PROGRAM)", \ ++ $^, \ ++ "openssl-devel / libssl-dev version >= 1.1.0", \ ++ "HAVE_OPENSSL=0", \ ++ "-I.") ++ touch $@ +--- /dev/null ++++ b/genprotimg/src/common.h +@@ -0,0 +1,39 @@ ++#ifndef COMMON_H ++#define COMMON_H ++ ++#define GETTEXT_PACKAGE "genprotimg" ++#include ++#include ++ ++#include "boot/linux_layout.h" ++#include "lib/zt_common.h" ++ ++static const gchar tool_name[] = "genprotimg"; ++static const gchar copyright_notice[] = "Copyright IBM Corp. 2020"; ++ ++/* default values */ ++#define GENPROTIMG_STAGE3A_PATH (STRINGIFY(PKGDATADIR) "/stage3a.bin") ++#define GENPROTIMG_STAGE3B_PATH (STRINGIFY(PKGDATADIR) "/stage3b_reloc.bin") ++ ++#define PSW_SHORT_ADDR_MASK 0x000000007FFFFFFFULL ++#define PSW_MASK_BA 0x0000000080000000ULL ++#define PSW_MASK_EA 0x0000000100000000ULL ++#define PSW_MASK_BIT_12 0x0008000000000000ULL ++ ++#define DEFAULT_INITIAL_PSW_ADDR IMAGE_ENTRY ++#define DEFAULT_INITIAL_PSW_MASK (PSW_MASK_EA | PSW_MASK_BA) ++ ++#define DO_PRAGMA(x) _Pragma(#x) ++ ++# ifdef __clang__ ++# define WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(...) \ ++ DO_PRAGMA(clang diagnostic push) \ ++ DO_PRAGMA(clang diagnostic ignored "-Wunused-function") \ ++ G_DEFINE_AUTOPTR_CLEANUP_FUNC(__VA_ARGS__) \ ++ DO_PRAGMA(clang diagnostic pop) ++# else ++# define WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(...) \ ++ G_DEFINE_AUTOPTR_CLEANUP_FUNC(__VA_ARGS__) ++# endif ++ ++#endif +--- /dev/null ++++ b/genprotimg/src/genprotimg.c +@@ -0,0 +1,181 @@ ++/* ++ * genprotimg - build relocatable secure images ++ * ++ * Copyright IBM Corp. 2020 ++ * ++ * s390-tools is free software; you can redistribute it and/or modify ++ * it under the terms of the MIT license. See LICENSE for details. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "common.h" ++#include "pv/pv_args.h" ++#include "pv/pv_image.h" ++ ++enum { ++ LOG_LEVEL_CRITICAL = 0, ++ LOG_LEVEL_INFO = 1, ++ LOG_LEVEL_DEBUG = 2, ++}; ++ ++static gint log_level = LOG_LEVEL_CRITICAL; ++static gchar *tmp_dir; ++ ++static void rmdir_recursive(gchar *dir_path, GError **err) ++{ ++ const gchar *file = NULL; ++ g_autoptr(GDir) d = NULL; ++ ++ if (!dir_path) ++ return; ++ ++ d = g_dir_open(dir_path, 0, err); ++ if (!d) { ++ g_set_error(err, G_FILE_ERROR, ++ (gint)g_file_error_from_errno(errno), ++ _("Failed to open directory '%s': %s"), dir_path, ++ g_strerror(errno)); ++ return; ++ } ++ ++ while ((file = g_dir_read_name(d)) != NULL) { ++ g_autofree gchar *file_path = ++ g_build_filename(dir_path, file, NULL); ++ /* ignore error */ ++ (void)g_unlink(file_path); ++ } ++ ++ if (g_rmdir(dir_path) != 0) { ++ g_set_error(err, G_FILE_ERROR, ++ (gint)g_file_error_from_errno(errno), ++ _("Failed to remove directory '%s': %s"), dir_path, ++ g_strerror(errno)); ++ return; ++ } ++} ++ ++static void sig_term_handler(int signal G_GNUC_UNUSED) ++{ ++ rmdir_recursive(tmp_dir, NULL); ++ exit(EXIT_FAILURE); ++} ++ ++static void log_handler_cb(const gchar *log_domain G_GNUC_UNUSED, ++ GLogLevelFlags level, const gchar *message, ++ gpointer user_data G_GNUC_UNUSED) ++{ ++ const gchar *prefix = ""; ++ ++ /* filter out messages depending on debugging level */ ++ if ((level & G_LOG_LEVEL_DEBUG) && log_level < LOG_LEVEL_DEBUG) ++ return; ++ ++ if ((level & G_LOG_LEVEL_INFO) && log_level < LOG_LEVEL_INFO) ++ return; ++ ++ if (level & G_LOG_LEVEL_WARNING) ++ prefix = "WARNING: "; ++ ++ if (level & G_LOG_LEVEL_ERROR) ++ prefix = "ERROR: "; ++ ++ if (level & (G_LOG_LEVEL_WARNING | G_LOG_LEVEL_ERROR)) ++ g_printerr("%s%s\n", prefix, message); ++ else ++ g_print("%s%s\n", prefix, message); ++} ++ ++static void setup_prgname(const gchar *name) ++{ ++ g_set_prgname(name); ++ g_set_application_name(_(name)); ++} ++ ++static void setup_handler(const gint *signals, const gsize signals_n) ++{ ++ /* set up logging handler */ ++ g_log_set_handler(NULL, ++ G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | ++ G_LOG_FLAG_RECURSION, ++ log_handler_cb, NULL); ++ ++ /* set signal handler */ ++ for (gsize i = 0; i < signals_n; i++) ++ signal(signals[i], sig_term_handler); ++} ++ ++static void remove_signal_handler(const gint *signals, const gsize signals_n) ++{ ++ for (gsize i = 0; i < signals_n; i++) ++ signal(signals[i], SIG_DFL); ++} ++ ++gint main(gint argc, gchar *argv[]) ++{ ++ g_autoptr(PvArgs) args = pv_args_new(); ++ gint signals[] = { SIGINT, SIGTERM }; ++ g_autoptr(PvImage) img = NULL; ++ gint ret = EXIT_FAILURE; ++ GError *err = NULL; ++ ++ setlocale(LC_CTYPE, ""); ++ setup_prgname(tool_name); ++ setup_handler(signals, G_N_ELEMENTS(signals)); ++ ++ if (pv_args_parse_options(args, &argc, &argv, &err) < 0) ++ goto error; ++ ++ /* set new log level */ ++ log_level = args->log_level; ++ ++ /* if the user has not specified a temporary directory let's ++ * create one ++ */ ++ if (!args->tmp_dir) { ++ tmp_dir = g_dir_make_tmp("genprotimg-XXXXXX", &err); ++ if (!tmp_dir) ++ goto error; ++ args->tmp_dir = g_strdup(tmp_dir); ++ } ++ ++ /* allocate and initialize ``pv_img`` data structure */ ++ img = pv_img_new(args, GENPROTIMG_STAGE3A_PATH, &err); ++ if (!img) ++ goto error; ++ ++ /* add user components: `args->comps` must be sorted by the ++ * component type => by memory address ++ */ ++ for (GSList *iterator = args->comps; iterator; iterator = iterator->next) { ++ const PvArg *arg = iterator->data; ++ ++ if (pv_img_add_component(img, arg, &err) < 0) ++ goto error; ++ } ++ ++ if (pv_img_finalize(img, GENPROTIMG_STAGE3B_PATH, &err) < 0) ++ goto error; ++ ++ if (pv_img_write(img, args->output_path, &err) < 0) ++ goto error; ++ ++ ret = EXIT_SUCCESS; ++ ++error: ++ if (err) { ++ fputs(err->message, stderr); ++ fputc('\n', stderr); ++ g_clear_error(&err); ++ } ++ rmdir_recursive(tmp_dir, NULL); ++ remove_signal_handler(signals, G_N_ELEMENTS(signals)); ++ g_free(tmp_dir); ++ exit(ret); ++} +--- /dev/null ++++ b/genprotimg/src/include/pv_crypto_def.h +@@ -0,0 +1,25 @@ ++/* ++ * PV cryptography related definitions ++ * ++ * Copyright IBM Corp. 2020 ++ * ++ * s390-tools is free software; you can redistribute it and/or modify ++ * it under the terms of the MIT license. See LICENSE for details. ++ */ ++ ++#ifndef PV_CRYPTO_DEF_H ++#define PV_CRYPTO_DEF_H ++ ++#include ++ ++#include "lib/zt_common.h" ++ ++union ecdh_pub_key { ++ struct { ++ uint8_t x[80]; ++ uint8_t y[80]; ++ }; ++ uint8_t data[160]; ++} __packed; ++ ++#endif +--- /dev/null ++++ b/genprotimg/src/include/pv_hdr_def.h +@@ -0,0 +1,84 @@ ++/* ++ * PV header definitions ++ * ++ * Copyright IBM Corp. 2020 ++ * ++ * s390-tools is free software; you can redistribute it and/or modify ++ * it under the terms of the MIT license. See LICENSE for details. ++ */ ++ ++#ifndef PV_HDR_DEF_H ++#define PV_HDR_DEF_H ++ ++#include ++ ++#include "boot/s390.h" ++#include "lib/zt_common.h" ++#include "utils/crypto.h" ++ ++#include "pv_crypto_def.h" ++ ++/* Magic number which is used to identify the file containing the PV ++ * header ++ */ ++#define PV_MAGIC_NUMBER 0x49424d5365634578ULL ++#define PV_VERSION_1 0x00000100U ++ ++/* prevent Ultravisor decryption during unpack operation */ ++#define PV_CFLAG_NO_DECRYPTION 0x10000000ULL ++ ++/* maxima for the PV version 1 */ ++#define PV_V1_IPIB_MAX_SIZE PAGE_SIZE ++#define PV_V1_PV_HDR_MAX_SIZE (2 * PAGE_SIZE) ++ ++typedef struct pv_hdr_key_slot { ++ uint8_t digest_key[SHA256_DIGEST_LENGTH]; ++ uint8_t wrapped_key[32]; ++ uint8_t tag[AES_256_GCM_TAG_SIZE]; ++} __packed PvHdrKeySlot; ++ ++typedef struct pv_hdr_opt_item { ++ uint32_t otype; ++ uint8_t ibk[32]; ++ uint8_t data[]; ++} __packed PvHdrOptItem; ++ ++/* integrity protected data (by GCM tag), but non-encrypted */ ++struct pv_hdr_head { ++ uint64_t magic; ++ uint32_t version; ++ uint32_t phs; ++ uint8_t iv[AES_256_GCM_IV_SIZE]; ++ uint32_t res1; ++ uint64_t nks; ++ uint64_t sea; ++ uint64_t nep; ++ uint64_t pcf; ++ union ecdh_pub_key cust_pub_key; ++ uint8_t pld[SHA512_DIGEST_LENGTH]; ++ uint8_t ald[SHA512_DIGEST_LENGTH]; ++ uint8_t tld[SHA512_DIGEST_LENGTH]; ++} __packed; ++ ++/* Must not have any padding */ ++struct pv_hdr_encrypted { ++ uint8_t cust_comm_key[32]; ++ uint8_t img_enc_key_1[AES_256_XTS_KEY_SIZE / 2]; ++ uint8_t img_enc_key_2[AES_256_XTS_KEY_SIZE / 2]; ++ struct psw_t psw; ++ uint64_t scf; ++ uint32_t noi; ++ uint32_t res2; ++}; ++STATIC_ASSERT(sizeof(struct pv_hdr_encrypted) == ++ 32 + 32 + 32 + sizeof(struct psw_t) + 8 + 4 + 4) ++ ++typedef struct pv_hdr { ++ struct pv_hdr_head head; ++ struct pv_hdr_key_slot *slots; ++ struct pv_hdr_encrypted *encrypted; ++ struct pv_hdr_opt_item **optional_items; ++ uint8_t tag[AES_256_GCM_TAG_SIZE]; ++} PvHdr; ++ ++#endif +--- /dev/null ++++ b/genprotimg/src/pv/pv_args.c +@@ -0,0 +1,405 @@ ++/* ++ * PV arguments related definitions and functions ++ * ++ * Copyright IBM Corp. 2020 ++ * ++ * s390-tools is free software; you can redistribute it and/or modify ++ * it under the terms of the MIT license. See LICENSE for details. ++ */ ++ ++#include ++#include ++ ++#include "common.h" ++ ++#include "pv_comp.h" ++#include "pv_error.h" ++#include "pv_args.h" ++ ++static gchar summary[] = ++ "Use genprotimg to create a protected virtualization kernel image file,\n" ++ "which can be loaded using zipl or QEMU."; ++ ++static gint pv_arg_compare(gconstpointer arg_1, gconstpointer arg_2) ++{ ++ g_assert(arg_1); ++ g_assert(arg_2); ++ ++ PvComponentType a = ((PvArg *)arg_1)->type; ++ PvComponentType b = ((PvArg *)arg_2)->type; ++ ++ if (a < b) ++ return -1; ++ if (a == b) ++ return 0; ++ return 1; ++} ++ ++static gint pv_arg_has_type(gconstpointer arg, gconstpointer type) ++{ ++ const PvArg *c = arg; ++ const PvComponentType *t = type; ++ ++ g_assert(arg); ++ ++ if (c->type == *t) ++ return 0; ++ if (c->type < *t) ++ return -1; ++ return 1; ++} ++ ++static gint pv_args_set_defaults(PvArgs *args, GError **err G_GNUC_UNUSED) ++{ ++ if (!args->psw_addr) ++ args->psw_addr = ++ g_strdup_printf("0x%lx", DEFAULT_INITIAL_PSW_ADDR); ++ ++ return 0; ++} ++ ++static gint pv_args_validate_options(PvArgs *args, GError **err) ++{ ++ PvComponentType KERNEL = PV_COMP_TYPE_KERNEL; ++ ++ if (args->unused_values->len > 0) { ++ g_autofree gchar *unused = NULL; ++ ++ for (gsize i = args->unused_values->len; i > 0; i--) { ++ g_autofree gchar *tmp = unused; ++ ++ unused = g_strjoin(" ", g_ptr_array_index(args->unused_values, i - 1), ++ tmp, ++ NULL); ++ } ++ ++ g_set_error(err, PV_PARSE_ERROR, PR_PARSE_ERROR_INVALID_ARGUMENT, ++ _("Unrecognized arguments: '%s'.\nUse 'genprotimg --help' for more information"), ++ unused); ++ return -1; ++ } ++ ++ if (!args->output_path) { ++ g_set_error(err, PV_PARSE_ERROR, PR_PARSE_ERROR_MISSING_ARGUMENT, ++ _("Option '--output' is required.\nUse 'genprotimg --help' for more information")); ++ return -1; ++ } ++ ++ if (!g_slist_find_custom(args->comps, &KERNEL, pv_arg_has_type)) { ++ g_set_error(err, PV_PARSE_ERROR, PR_PARSE_ERROR_MISSING_ARGUMENT, ++ _("Option '--image' is required.\nUse 'genprotimg --help' for more information")); ++ return -1; ++ } ++ ++ if (!args->host_keys || g_strv_length(args->host_keys) == 0) { ++ g_set_error(err, PV_PARSE_ERROR, PR_PARSE_ERROR_MISSING_ARGUMENT, ++ _("Option '--host-key-document' is required.\nUse 'genprotimg --help' for more information")); ++ return -1; ++ } ++ ++ if (!args->no_verify) { ++ g_set_error(err, PV_PARSE_ERROR, PR_PARSE_ERROR_MISSING_ARGUMENT, ++ _("Use the option '--no-verify' as the verification support is not available yet.")); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static gboolean cb_add_component(const gchar *option, const gchar *value, ++ PvArgs *args, GError **err) ++{ ++ PvArg *comp = NULL; ++ gint type = -1; ++ ++ if (g_str_equal(option, "-i") || g_str_equal(option, "--image")) ++ type = PV_COMP_TYPE_KERNEL; ++ if (g_str_equal(option, "-r") || g_str_equal(option, "--ramdisk")) ++ type = PV_COMP_TYPE_INITRD; ++ if (g_str_equal(option, "-p") || g_str_equal(option, "--parmfile")) ++ type = PV_COMP_TYPE_CMDLINE; ++ ++ if (type < 0) { ++ g_set_error(err, PV_PARSE_ERROR, PV_PARSE_ERROR_SYNTAX, ++ _("Invalid option '%s': "), option); ++ return FALSE; ++ } ++ ++ if (g_slist_find_custom(args->comps, &type, pv_arg_has_type)) { ++ g_set_error(err, PV_PARSE_ERROR, PV_PARSE_ERROR_SYNTAX, ++ _("Multiple values for option '%s'"), option); ++ return FALSE; ++ } ++ ++ comp = pv_arg_new((PvComponentType)type, value); ++ args->comps = g_slist_insert_sorted(args->comps, comp, pv_arg_compare); ++ return TRUE; ++} ++ ++static gboolean cb_set_string_option(const gchar *option, const gchar *value, ++ PvArgs *args, GError **err) ++{ ++ gchar **args_option = NULL; ++ ++ if (g_str_equal(option, "-o") || g_str_equal(option, "--output")) ++ args_option = &args->output_path; ++ if (g_str_equal(option, "--x-comp-key")) ++ args_option = &args->xts_key_path; ++ if (g_str_equal(option, "--x-comm-key")) ++ args_option = &args->cust_comm_key_path; ++ if (g_str_equal(option, "--x-header-key")) ++ args_option = &args->cust_root_key_path; ++ if (g_str_equal(option, "--x-pcf")) ++ args_option = &args->pcf; ++ if (g_str_equal(option, "--x-psw")) ++ args_option = &args->psw_addr; ++ if (g_str_equal(option, "--x-scf")) ++ args_option = &args->scf; ++ ++ if (!args_option) { ++ g_set_error(err, PV_PARSE_ERROR, PV_PARSE_ERROR_SYNTAX, ++ _("Invalid option '%s': "), option); ++ return FALSE; ++ } ++ ++ if (*args_option) { ++ g_set_error(err, PV_PARSE_ERROR, PV_PARSE_ERROR_SYNTAX, ++ _("Multiple values for option '%s'"), option); ++ return FALSE; ++ } ++ ++ *args_option = g_strdup(value); ++ return TRUE; ++} ++ ++static gboolean cb_set_log_level(const gchar *option G_GNUC_UNUSED, ++ const gchar *value G_GNUC_UNUSED, PvArgs *args, ++ GError **err G_GNUC_UNUSED) ++{ ++ args->log_level++; ++ return TRUE; ++} ++ ++static gboolean cb_remaining_values(const gchar *option G_GNUC_UNUSED, ++ const gchar *value, PvArgs *args, ++ GError **err G_GNUC_UNUSED) ++{ ++ g_ptr_array_add(args->unused_values, g_strdup(value)); ++ return TRUE; ++} ++ ++#define INDENT " " ++ ++gint pv_args_parse_options(PvArgs *args, gint *argc, gchar **argv[], ++ GError **err) ++{ ++ g_autoptr(GOptionContext) context = NULL; ++ gboolean print_version = FALSE; ++ GOptionGroup *group, *x_group; ++ ++ g_autofree gchar *psw_desc = g_strdup_printf( ++ _("Load from the specified hexadecimal ADDRESS.\n" INDENT ++ "Optional; default: '0x%lx'."), ++ DEFAULT_INITIAL_PSW_ADDR); ++ GOptionEntry entries[] = { ++ { .long_name = "host-key-document", ++ .short_name = 'k', ++ .flags = G_OPTION_FLAG_NONE, ++ .arg = G_OPTION_ARG_FILENAME_ARRAY, ++ .arg_data = &args->host_keys, ++ .description = ++ _("FILE specifies a host-key document. At least\n" INDENT ++ "one is required."), ++ .arg_description = _("FILE") }, ++ { .long_name = "output", ++ .short_name = 'o', ++ .flags = G_OPTION_FLAG_FILENAME, ++ .arg = G_OPTION_ARG_CALLBACK, ++ .arg_data = cb_set_string_option, ++ .description = _("Set FILE as the output file."), ++ .arg_description = _("FILE") }, ++ { .long_name = "image", ++ .short_name = 'i', ++ .flags = G_OPTION_FLAG_FILENAME, ++ .arg = G_OPTION_ARG_CALLBACK, ++ .arg_data = cb_add_component, ++ .description = _("Use IMAGE as the Linux kernel image."), ++ .arg_description = _("IMAGE") }, ++ { .long_name = "ramdisk", ++ .short_name = 'r', ++ .flags = G_OPTION_FLAG_OPTIONAL_ARG | G_OPTION_FLAG_FILENAME, ++ .arg = G_OPTION_ARG_CALLBACK, ++ .arg_data = cb_add_component, ++ .description = _("Use RAMDISK as the initial RAM disk\n" INDENT ++ "(optional)."), ++ .arg_description = _("RAMDISK") }, ++ { .long_name = "parmfile", ++ .short_name = 'p', ++ .flags = G_OPTION_FLAG_OPTIONAL_ARG | G_OPTION_FLAG_FILENAME, ++ .arg = G_OPTION_ARG_CALLBACK, ++ .arg_data = cb_add_component, ++ .description = _("Use the kernel parameters stored in PARMFILE\n" INDENT ++ "(optional)."), ++ .arg_description = _("PARMFILE") }, ++ { .long_name = "no-verify", ++ .short_name = 0, ++ .flags = G_OPTION_FLAG_NONE, ++ .arg = G_OPTION_ARG_NONE, ++ .arg_data = &args->no_verify, ++ .description = _("Disable the host-key document verification\n" INDENT ++ "(optional)."), ++ .arg_description = NULL }, ++ { .long_name = "verbose", ++ .short_name = 'V', ++ .flags = G_OPTION_FLAG_NO_ARG, ++ .arg = G_OPTION_ARG_CALLBACK, ++ .arg_data = cb_set_log_level, ++ .description = _("Provide more detailed output (optional)."), ++ .arg_description = NULL }, ++ { .long_name = "version", ++ .short_name = 'v', ++ .flags = G_OPTION_FLAG_NONE, ++ .arg = G_OPTION_ARG_NONE, ++ .arg_data = &print_version, ++ .description = _("Print the version and exit."), ++ .arg_description = NULL }, ++ { .long_name = G_OPTION_REMAINING, ++ .short_name = 0, ++ .flags = 0, ++ .arg = G_OPTION_ARG_CALLBACK, ++ .arg_data = cb_remaining_values, ++ .description = NULL, ++ .arg_description = NULL }, ++ { 0 }, ++ }; ++ ++ GOptionEntry x_entries[] = { ++ { .long_name = "x-comm-key", ++ .short_name = 0, ++ .flags = G_OPTION_FLAG_FILENAME, ++ .arg = G_OPTION_ARG_CALLBACK, ++ .arg_data = cb_set_string_option, ++ .description = _( ++ "Use FILE as the customer communication key.\n" INDENT ++ "Optional; default: auto-generated."), ++ .arg_description = _("FILE") }, ++ { .long_name = "x-comp-key", ++ .short_name = 0, ++ .flags = G_OPTION_FLAG_FILENAME, ++ .arg = G_OPTION_ARG_CALLBACK, ++ .arg_data = cb_set_string_option, ++ .description = _( ++ "Use FILE as the AES 256-bit XTS key\n" INDENT ++ "that is used for the component encryption.\n" INDENT ++ "Optional; default: auto-generated."), ++ .arg_description = _("FILE") }, ++ { .long_name = "x-header-key", ++ .short_name = 0, ++ .flags = G_OPTION_FLAG_FILENAME, ++ .arg = G_OPTION_ARG_CALLBACK, ++ .arg_data = cb_set_string_option, ++ .description = _( ++ "Use FILE as the AES 256-bit GCM header key\n" INDENT ++ "that protects the PV header.\n" INDENT ++ "Optional; default: auto-generated."), ++ .arg_description = _("FILE") }, ++ { .long_name = "x-pcf", ++ .short_name = 0, ++ .flags = G_OPTION_FLAG_NONE, ++ .arg = G_OPTION_ARG_CALLBACK, ++ .arg_data = cb_set_string_option, ++ .description = ++ _("Specify the plaintext control flags\n" INDENT ++ "as a hexadecimal value.\n" INDENT ++ "Optional; default: '0x0'."), ++ .arg_description = _("VALUE") }, ++ { .long_name = "x-psw", ++ .short_name = 0, ++ .flags = G_OPTION_FLAG_NONE, ++ .arg = G_OPTION_ARG_CALLBACK, ++ .arg_data = cb_set_string_option, ++ .description = psw_desc, ++ .arg_description = _("ADDRESS") }, ++ { .long_name = "x-scf", ++ .short_name = 0, ++ .flags = G_OPTION_FLAG_NONE, ++ .arg = G_OPTION_ARG_CALLBACK, ++ .arg_data = cb_set_string_option, ++ .description = _("Specify the secret control flags\n" INDENT ++ "as a hexadecimal value.\n" INDENT ++ "Optional; default: '0x0'."), ++ .arg_description = _("VALUE") }, ++ { 0 }, ++ }; ++ ++ context = g_option_context_new( ++ _("- Create a protected virtualization image")); ++ g_option_context_set_summary(context, _(summary)); ++ group = g_option_group_new(GETTEXT_PACKAGE, _("Application Options:"), ++ _("Show help options"), args, NULL); ++ g_option_group_add_entries(group, entries); ++ g_option_context_set_main_group(context, group); ++ ++ x_group = g_option_group_new("experimental", _("Experimental Options:"), ++ _("Show experimental options"), args, NULL); ++ g_option_group_add_entries(x_group, x_entries); ++ g_option_context_add_group(context, x_group); ++ if (!g_option_context_parse(context, argc, argv, err)) ++ return -1; ++ ++ if (print_version) { ++ g_printf(_("%s version %s\n"), tool_name, RELEASE_STRING); ++ g_printf("%s\n", copyright_notice); ++ exit(EXIT_SUCCESS); ++ } ++ ++ if (pv_args_set_defaults(args, err) < 0) ++ return -1; ++ ++ return pv_args_validate_options(args, err); ++} ++ ++PvArgs *pv_args_new(void) ++{ ++ g_autoptr(PvArgs) args = g_new0(PvArgs, 1); ++ ++ args->unused_values = g_ptr_array_new_with_free_func(g_free); ++ return g_steal_pointer(&args); ++} ++ ++void pv_args_free(PvArgs *args) ++{ ++ if (!args) ++ return; ++ ++ g_free(args->pcf); ++ g_free(args->scf); ++ g_free(args->psw_addr); ++ g_free(args->cust_root_key_path); ++ g_free(args->cust_comm_key_path); ++ g_free(args->gcm_iv_path); ++ g_strfreev(args->host_keys); ++ g_free(args->xts_key_path); ++ g_slist_free_full(args->comps, (GDestroyNotify)pv_arg_free); ++ g_ptr_array_free(args->unused_values, TRUE); ++ g_free(args->output_path); ++ g_free(args->tmp_dir); ++ g_free(args); ++} ++ ++void pv_arg_free(PvArg *arg) ++{ ++ if (!arg) ++ return; ++ ++ g_free(arg->path); ++ g_free(arg); ++} ++PvArg *pv_arg_new(PvComponentType type, const gchar *path) ++{ ++ g_autoptr(PvArg) ret = g_new0(struct pv_arg, 1); ++ ++ ret->type = type; ++ ret->path = g_strdup(path); ++ return g_steal_pointer(&ret); ++} +--- /dev/null ++++ b/genprotimg/src/pv/pv_args.h +@@ -0,0 +1,53 @@ ++/* ++ * PV arguments related definitions and functions ++ * ++ * Copyright IBM Corp. 2020 ++ * ++ * s390-tools is free software; you can redistribute it and/or modify ++ * it under the terms of the MIT license. See LICENSE for details. ++ */ ++ ++#ifndef PV_ARGS_H ++#define PV_ARGS_H ++ ++#include ++ ++#include "pv_comp.h" ++ ++typedef struct pv_arg { ++ PvComponentType type; ++ gchar *path; ++} PvArg; ++ ++PvArg *pv_arg_new(PvComponentType type, const gchar *path); ++void pv_arg_free(PvArg *arg); ++ ++typedef struct { ++ gint log_level; ++ gint no_verify; ++ gchar *pcf; ++ gchar *scf; ++ gchar *psw_addr; /* PSW address which will be used for the start of ++ * the actual component (e.g. Linux kernel) ++ */ ++ gchar *cust_root_key_path; ++ gchar *cust_comm_key_path; ++ gchar *gcm_iv_path; ++ gchar **host_keys; ++ gchar *xts_key_path; ++ GSList *comps; ++ gchar *output_path; ++ gchar *tmp_dir; ++ GPtrArray *unused_values; ++} PvArgs; ++ ++PvArgs *pv_args_new(void); ++void pv_args_free(PvArgs *args); ++ ++gint pv_args_parse_options(PvArgs *args, gint *argc, gchar **argv[], ++ GError **err); ++ ++WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(PvArg, pv_arg_free) ++WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(PvArgs, pv_args_free) ++ ++#endif +--- /dev/null ++++ b/genprotimg/src/pv/pv_comp.c +@@ -0,0 +1,446 @@ ++/* ++ * PV component related definitions and functions ++ * ++ * Copyright IBM Corp. 2020 ++ * ++ * s390-tools is free software; you can redistribute it and/or modify ++ * it under the terms of the MIT license. See LICENSE for details. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "boot/s390.h" ++#include "common.h" ++#include "utils/align.h" ++#include "utils/buffer.h" ++#include "utils/crypto.h" ++#include "utils/file_utils.h" ++ ++#include "pv_comp.h" ++#include "pv_error.h" ++ ++static void comp_file_free(CompFile *comp) ++{ ++ if (!comp) ++ return; ++ ++ g_free(comp->path); ++ g_free(comp); ++} ++ ++WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(CompFile, comp_file_free) ++ ++static PvComponent *pv_component_new(PvComponentType type, gsize size, ++ PvComponentDataType d_type, void **data, ++ GError **err) ++{ ++ g_autoptr(PvComponent) ret = g_new0(PvComponent, 1); ++ ++ g_assert(type >= 0 && type <= UINT16_MAX); ++ ++ ret->type = (int)type; ++ ret->d_type = (int)d_type; ++ ret->data = g_steal_pointer(data); ++ ret->orig_size = size; ++ ++ if (generate_tweak(&ret->tweak, (uint16_t)type, err) < 0) ++ return NULL; ++ ++ return g_steal_pointer(&ret); ++} ++ ++PvComponent *pv_component_new_file(PvComponentType type, const gchar *path, ++ GError **err) ++{ ++ g_autoptr(CompFile) file = g_new0(CompFile, 1); ++ gsize size; ++ gint rc; ++ ++ g_assert(path != NULL); ++ ++ rc = file_size(path, &size, err); ++ if (rc < 0) ++ return NULL; ++ ++ file->path = g_strdup(path); ++ file->size = size; ++ return pv_component_new(type, size, DATA_FILE, (void **)&file, err); ++} ++ ++PvComponent *pv_component_new_buf(PvComponentType type, const Buffer *buf, ++ GError **err) ++{ ++ g_assert(buf); ++ ++ g_autoptr(Buffer) dup_buf = buffer_dup(buf, FALSE); ++ return pv_component_new(type, buf->size, DATA_BUFFER, (void **)&dup_buf, ++ err); ++} ++ ++void pv_component_free(PvComponent *component) ++{ ++ if (!component) ++ return; ++ ++ switch ((PvComponentDataType)component->d_type) { ++ case DATA_BUFFER: ++ buffer_clear(&component->buf); ++ break; ++ case DATA_FILE: ++ comp_file_free(component->file); ++ break; ++ } ++ ++ g_free(component); ++} ++ ++gint pv_component_type(const PvComponent *component) ++{ ++ return component->type; ++} ++ ++const gchar *pv_component_name(const PvComponent *component) ++{ ++ gint type = pv_component_type(component); ++ ++ switch ((PvComponentType)type) { ++ case PV_COMP_TYPE_KERNEL: ++ return "kernel"; ++ case PV_COMP_TYPE_INITRD: ++ return "ramdisk"; ++ case PV_COMP_TYPE_CMDLINE: ++ return "parmline"; ++ case PV_COMP_TYPE_STAGE3B: ++ return "stage3b"; ++ } ++ ++ g_assert_not_reached(); ++} ++ ++uint64_t pv_component_size(const PvComponent *component) ++{ ++ switch ((PvComponentDataType)component->d_type) { ++ case DATA_BUFFER: ++ return component->buf->size; ++ case DATA_FILE: ++ return component->file->size; ++ } ++ ++ g_assert_not_reached(); ++} ++ ++uint64_t pv_component_get_src_addr(const PvComponent *component) ++{ ++ return component->src_addr; ++} ++ ++uint64_t pv_component_get_orig_size(const PvComponent *component) ++{ ++ return component->orig_size; ++} ++ ++uint64_t pv_component_get_tweak_prefix(const PvComponent *component) ++{ ++ return GUINT64_FROM_BE(component->tweak.cmp_idx.data); ++} ++ ++gboolean pv_component_is_stage3b(const PvComponent *component) ++{ ++ return pv_component_type(component) == PV_COMP_TYPE_STAGE3B; ++} ++ ++gint pv_component_align_and_encrypt(PvComponent *component, const gchar *tmp_path, ++ void *opaque, GError **err) ++{ ++ struct cipher_parms *parms = opaque; ++ ++ switch ((PvComponentDataType)component->d_type) { ++ case DATA_BUFFER: { ++ g_autoptr(Buffer) enc_buf = NULL; ++ ++ if (!(IS_PAGE_ALIGNED(pv_component_size(component)))) { ++ g_autoptr(Buffer) new = NULL; ++ ++ /* create a page aligned copy */ ++ new = buffer_dup(component->buf, TRUE); ++ buffer_clear(&component->buf); ++ component->buf = g_steal_pointer(&new); ++ } ++ enc_buf = encrypt_buf(parms, component->buf, err); ++ if (!enc_buf) ++ return -1; ++ ++ buffer_clear(&component->buf); ++ component->buf = g_steal_pointer(&enc_buf); ++ return 0; ++ } ++ case DATA_FILE: { ++ const gchar *comp_name = pv_component_name(component); ++ gchar *path_in = component->file->path; ++ g_autofree gchar *path_out = NULL; ++ gsize orig_size; ++ gsize prep_size; ++ ++ g_assert(path_in); ++ ++ path_out = g_build_filename(tmp_path, comp_name, NULL); ++ if (encrypt_file(parms, path_in, path_out, &orig_size, ++ &prep_size, err) < 0) ++ return -1; ++ ++ if (component->orig_size != orig_size) { ++ g_set_error(err, G_FILE_ERROR, PV_ERROR_INTERNAL, ++ _("File has changed during the preparation '%s'"), ++ path_out); ++ return -1; ++ } ++ ++ g_free(component->file->path); ++ component->file->size = prep_size; ++ component->file->path = g_steal_pointer(&path_out); ++ return 0; ++ } ++ } ++ ++ g_assert_not_reached(); ++} ++ ++/* Page align the size of the component */ ++gint pv_component_align(PvComponent *component, const gchar *tmp_path, ++ void *opaque G_GNUC_UNUSED, GError **err) ++{ ++ if (IS_PAGE_ALIGNED(pv_component_size(component))) ++ return 0; ++ ++ switch (component->d_type) { ++ case DATA_BUFFER: { ++ g_autoptr(Buffer) buf = NULL; ++ ++ buf = buffer_dup(component->buf, TRUE); ++ buffer_clear(&component->buf); ++ component->buf = g_steal_pointer(&buf); ++ return 0; ++ } break; ++ case DATA_FILE: { ++ const gchar *comp_name = pv_component_name(component); ++ g_autofree gchar *path_out = ++ g_build_filename(tmp_path, comp_name, NULL); ++ gchar *path_in = component->file->path; ++ gsize size_out; ++ ++ if (pad_file_right(path_out, path_in, &size_out, PAGE_SIZE, ++ err) < 0) ++ return -1; ++ ++ g_free(component->file->path); ++ component->file->path = g_steal_pointer(&path_out); ++ component->file->size = size_out; ++ return 0; ++ } break; ++ } ++ ++ g_assert_not_reached(); ++} ++ ++/* Convert uint64_t address to byte array */ ++static void uint64_to_uint8_buf(uint8_t dst[8], uint64_t addr) ++{ ++ uint8_t *p = (uint8_t *)&addr; ++ ++ g_assert(dst); ++ ++ for (gint i = 0; i < 8; i++) { ++ /* cppcheck-suppress objectIndex */ ++ dst[i] = p[i]; ++ } ++} ++ ++int64_t pv_component_update_ald(const PvComponent *comp, EVP_MD_CTX *ctx, ++ GError **err) ++{ ++ uint64_t addr = pv_component_get_src_addr(comp); ++ uint64_t size = pv_component_size(comp); ++ uint64_t cur = addr; ++ int64_t nep = 0; ++ ++ g_assert(IS_PAGE_ALIGNED(size) && size != 0); ++ ++ do { ++ uint64_t cur_be = GUINT64_TO_BE(cur); ++ uint8_t addr_buf[8]; ++ ++ uint64_to_uint8_buf(addr_buf, cur_be); ++ ++ if (EVP_DigestUpdate(ctx, addr_buf, sizeof(addr_buf)) != 1) { ++ g_set_error(err, PV_CRYPTO_ERROR, ++ PV_CRYPTO_ERROR_INTERNAL, ++ _("EVP_DigestUpdate failed")); ++ return -1; ++ } ++ ++ cur += PAGE_SIZE; ++ nep++; ++ } while (cur < addr + size); ++ ++ return nep; ++} ++ ++int64_t pv_component_update_pld(const PvComponent *comp, EVP_MD_CTX *ctx, ++ GError **err) ++{ ++ uint64_t size = pv_component_size(comp); ++ int64_t nep = 0; ++ ++ g_assert(IS_PAGE_ALIGNED(size) && size != 0); ++ ++ switch (comp->d_type) { ++ case DATA_BUFFER: { ++ const Buffer *buf = comp->buf; ++ ++ g_assert(buf->size <= INT64_MAX); ++ g_assert(buf->size == size); ++ ++ if (EVP_DigestUpdate(ctx, buf->data, buf->size) != 1) { ++ g_set_error(err, PV_CRYPTO_ERROR, ++ PV_CRYPTO_ERROR_INTERNAL, ++ _("EVP_DigestUpdate failed")); ++ return -1; ++ } ++ ++ nep = (int64_t)(buf->size / PAGE_SIZE); ++ break; ++ } ++ case DATA_FILE: { ++ const gchar *in_path = comp->file->path; ++ guchar in_buf[PAGE_SIZE]; ++ gsize num_bytes_read_total = 0; ++ gsize num_bytes_read = 0; ++ FILE *f_in; ++ ++ f_in = file_open(in_path, "rb", err); ++ if (!f_in) ++ return -1; ++ ++ do { ++ /* Read data in blocks. Update the digest ++ * context each read. ++ */ ++ if (file_read(f_in, in_buf, sizeof(*in_buf), ++ sizeof(in_buf), &num_bytes_read, ++ err) < 0) { ++ fclose(f_in); ++ return -1; ++ } ++ num_bytes_read_total += num_bytes_read; ++ ++ if (EVP_DigestUpdate(ctx, in_buf, sizeof(in_buf)) != 1) { ++ g_set_error(err, PV_CRYPTO_ERROR, ++ PV_CRYPTO_ERROR_INTERNAL, ++ _("EVP_DigestUpdate failed")); ++ fclose(f_in); ++ return -1; ++ } ++ ++ nep++; ++ } while (num_bytes_read_total < pv_component_size(comp) && ++ num_bytes_read != 0); ++ ++ if (num_bytes_read_total != pv_component_size(comp)) { ++ g_set_error(err, G_FILE_ERROR, PV_ERROR_INTERNAL, ++ _("'%s' has changed during the preparation"), ++ in_path); ++ fclose(f_in); ++ return -1; ++ } ++ fclose(f_in); ++ break; ++ } ++ default: ++ g_assert_not_reached(); ++ } ++ ++ return nep; ++} ++ ++int64_t pv_component_update_tld(const PvComponent *comp, EVP_MD_CTX *ctx, ++ GError **err) ++{ ++ uint64_t size = pv_component_size(comp); ++ const union tweak *tweak = &comp->tweak; ++ g_autoptr(BIGNUM) tweak_num = NULL; ++ int64_t nep = 0; ++ ++ g_assert(IS_PAGE_ALIGNED(size) && size != 0); ++ ++ tweak_num = BN_bin2bn(tweak->data, sizeof(tweak->data), NULL); ++ if (!tweak_num) { ++ g_set_error(err, PV_CRYPTO_ERROR, ++ PV_CRYPTO_ERROR_INTERNAL, ++ _("BN_bin2bn failed")); ++ } ++ ++ for (uint64_t cur = 0; cur < size; cur += PAGE_SIZE) { ++ guchar tmp[sizeof(tweak->data)] = { 0 }; ++ ++ g_assert(BN_num_bytes(tweak_num) >= 0); ++ g_assert(sizeof(tmp) - (guint)BN_num_bytes(tweak_num) > 0); ++ ++ if (BN_bn2binpad(tweak_num, tmp, sizeof(tmp)) < 0) { ++ g_set_error(err, PV_CRYPTO_ERROR, ++ PV_CRYPTO_ERROR_INTERNAL, ++ _("BN_bn2binpad failed")); ++ } ++ ++ if (EVP_DigestUpdate(ctx, tmp, sizeof(tmp)) != 1) { ++ g_set_error(err, PV_CRYPTO_ERROR, ++ PV_CRYPTO_ERROR_INTERNAL, ++ _("EVP_DigestUpdate failed")); ++ return -1; ++ } ++ ++ /* calculate new tweak value */ ++ if (BN_add_word(tweak_num, PAGE_SIZE) != 1) { ++ g_set_error(err, PV_CRYPTO_ERROR, ++ PV_CRYPTO_ERROR_INTERNAL, ++ _("BN_add_word failed")); ++ } ++ ++ nep++; ++ } ++ ++ return nep; ++} ++ ++gint pv_component_write(const PvComponent *component, FILE *f, GError **err) ++{ ++ uint64_t offset = pv_component_get_src_addr(component); ++ ++ g_assert(f); ++ ++ switch (component->d_type) { ++ case DATA_BUFFER: { ++ const Buffer *buf = component->buf; ++ ++ if (seek_and_write_buffer(f, buf, offset, err) < 0) ++ return -1; ++ ++ return 0; ++ } ++ case DATA_FILE: { ++ const CompFile *file = component->file; ++ ++ if (seek_and_write_file(f, file, offset, err) < 0) ++ return -1; ++ ++ return 0; ++ } ++ } ++ ++ g_assert_not_reached(); ++} +--- /dev/null ++++ b/genprotimg/src/pv/pv_comp.h +@@ -0,0 +1,78 @@ ++/* ++ * PV component related definitions and functions ++ * ++ * Copyright IBM Corp. 2020 ++ * ++ * s390-tools is free software; you can redistribute it and/or modify ++ * it under the terms of the MIT license. See LICENSE for details. ++ */ ++ ++#ifndef PV_COMP_H ++#define PV_COMP_H ++ ++#include ++#include ++#include ++ ++#include "utils/crypto.h" ++ ++/* The order of this enum also implicitly defines the order of the ++ * components within the PV image! ++ */ ++typedef enum { ++ PV_COMP_TYPE_KERNEL = 0, ++ PV_COMP_TYPE_CMDLINE = 1, ++ PV_COMP_TYPE_INITRD = 2, ++ PV_COMP_TYPE_STAGE3B = 3, ++} PvComponentType; ++ ++typedef enum { ++ DATA_FILE = 0, ++ DATA_BUFFER, ++} PvComponentDataType; ++ ++typedef struct comp_file { ++ gchar *path; ++ gsize size; ++} CompFile; ++ ++typedef struct { ++ gint type; /* PvComponentType */ ++ gint d_type; /* PvComponentDataType */ ++ union { ++ struct comp_file *file; ++ Buffer *buf; ++ void *data; ++ }; ++ uint64_t src_addr; ++ uint64_t orig_size; ++ union tweak tweak; /* used for the AES XTS encryption */ ++} PvComponent; ++ ++PvComponent *pv_component_new_file(PvComponentType type, const gchar *path, ++ GError **err); ++PvComponent *pv_component_new_buf(PvComponentType type, const Buffer *buf, ++ GError **err); ++void pv_component_free(PvComponent *component); ++gint pv_component_type(const PvComponent *component); ++const gchar *pv_component_name(const PvComponent *component); ++uint64_t pv_component_size(const PvComponent *component); ++uint64_t pv_component_get_src_addr(const PvComponent *component); ++uint64_t pv_component_get_orig_size(const PvComponent *component); ++uint64_t pv_component_get_tweak_prefix(const PvComponent *component); ++gboolean pv_component_is_stage3b(const PvComponent *component); ++gint pv_component_align_and_encrypt(PvComponent *component, const gchar *tmp_path, ++ void *opaque, GError **err); ++gint pv_component_align(PvComponent *component, const gchar *tmp_path, ++ void *opaque G_GNUC_UNUSED, GError **err); ++int64_t pv_component_update_pld(const PvComponent *comp, EVP_MD_CTX *ctx, ++ GError **err); ++int64_t pv_component_update_ald(const PvComponent *comp, EVP_MD_CTX *ctx, ++ GError **err); ++int64_t pv_component_update_tld(const PvComponent *comp, EVP_MD_CTX *ctx, ++ GError **err); ++gint pv_component_write(const PvComponent *component, FILE *f, GError **err); ++ ++WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(PvComponent, pv_component_free) ++ ++#endif +--- /dev/null ++++ b/genprotimg/src/pv/pv_comps.c +@@ -0,0 +1,252 @@ ++/* ++ * PV components related definitions and functions ++ * ++ * Copyright IBM Corp. 2020 ++ * ++ * s390-tools is free software; you can redistribute it and/or modify ++ * it under the terms of the MIT license. See LICENSE for details. ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include "boot/s390.h" ++#include "boot/stage3b.h" ++#include "common.h" ++#include "utils/align.h" ++#include "utils/crypto.h" ++ ++#include "pv_comp.h" ++#include "pv_comps.h" ++#include "pv_error.h" ++#include "pv_stage3.h" ++ ++struct _pv_img_comps { ++ gboolean finalized; ++ uint64_t next_src; ++ uint64_t nep; ++ EVP_MD_CTX *ald; /* context used for the hash of the addresses */ ++ EVP_MD_CTX *pld; /* context used for the hash of the pages content */ ++ EVP_MD_CTX *tld; /* context used for the hash of the tweaks */ ++ GSList *comps; /* elements sorted by component type */ ++}; ++ ++void pv_img_comps_free(PvImgComps *comps) ++{ ++ if (!comps) ++ return; ++ ++ EVP_MD_CTX_free(comps->ald); ++ EVP_MD_CTX_free(comps->pld); ++ EVP_MD_CTX_free(comps->tld); ++ g_slist_free_full(comps->comps, (GDestroyNotify)pv_component_free); ++ g_free(comps); ++} ++ ++PvImgComps *pv_img_comps_new(const EVP_MD *ald_md, const EVP_MD *pld_md, ++ const EVP_MD *tld_md, GError **err) ++{ ++ g_autoptr(PvImgComps) ret = g_new0(PvImgComps, 1); ++ ++ ret->ald = digest_ctx_new(ald_md, err); ++ if (!ret->ald) ++ return NULL; ++ ++ ret->pld = digest_ctx_new(pld_md, err); ++ if (!ret->pld) ++ return NULL; ++ ++ ret->tld = digest_ctx_new(tld_md, err); ++ if (!ret->tld) ++ return NULL; ++ ++ return g_steal_pointer(&ret); ++} ++ ++guint pv_img_comps_length(const PvImgComps *comps) ++{ ++ return g_slist_length(comps->comps); ++} ++ ++/* Update hashes and nep */ ++/* Returns 0 in case of success and -1 in case of a failure */ ++static gint pv_img_comps_hash_comp(PvImgComps *comps, const PvComponent *comp, ++ GError **err) ++{ ++ int64_t nep_1 = 0; ++ int64_t nep_2 = 0; ++ int64_t nep_3 = 0; ++ ++ /* update pld */ ++ nep_1 = pv_component_update_pld(comp, comps->pld, err); ++ if (nep_1 < 0) ++ return -1; ++ ++ /* update ald */ ++ nep_2 = pv_component_update_ald(comp, comps->ald, err); ++ if (nep_2 < 0) ++ return -1; ++ ++ /* update tld */ ++ nep_3 = pv_component_update_tld(comp, comps->tld, err); ++ if (nep_3 < 0) ++ return -1; ++ ++ g_assert(nep_1 == nep_2); ++ g_assert(nep_2 == nep_3); ++ ++ /* update comps->nep */ ++ g_assert_true(g_uint64_checked_add(&comps->nep, comps->nep, ++ (uint64_t)nep_1)); ++ return 0; ++} ++ ++gint pv_img_comps_add_component(PvImgComps *comps, PvComponent **comp, ++ GError **err) ++{ ++ g_assert(comp); ++ g_assert(*comp); ++ g_assert(comps); ++ g_assert(IS_PAGE_ALIGNED(comps->next_src)); ++ ++ uint64_t src_addr = comps->next_src; ++ uint64_t src_size = pv_component_size(*comp) ++ ? PAGE_ALIGN(pv_component_size(*comp)) ++ : PAGE_SIZE; ++ ++ if (comps->finalized) { ++ g_set_error(err, PV_COMPONENT_ERROR, PV_COMPONENT_ERROR_FINALIZED, ++ _("Failed to add component, image is already finalized")); ++ return -1; ++ } ++ ++ /* set the address of the component in the memory layout */ ++ (*comp)->src_addr = src_addr; ++ ++ g_info("%12s:\t0x%012lx (%12ld / %12ld Bytes)", ++ pv_component_name(*comp), pv_component_get_src_addr(*comp), ++ pv_component_size(*comp), pv_component_get_orig_size(*comp)); ++ ++ /* append the component and pass the responsibility of @comp ++ * to @comps ++ */ ++ comps->comps = g_slist_append(comps->comps, g_steal_pointer(comp)); ++ comps->next_src += src_size; ++ ++ g_assert(IS_PAGE_ALIGNED(comps->next_src)); ++ g_assert(!*comp); ++ return 0; ++} ++ ++struct stage3b_args *pv_img_comps_get_stage3b_args(const PvImgComps *comps, ++ struct psw_t *psw) ++{ ++ g_autofree struct stage3b_args *ret = g_new0(struct stage3b_args, 1); ++ ++ for (GSList *iterator = comps->comps; iterator; iterator = iterator->next) { ++ const PvComponent *img_comp = iterator->data; ++ uint64_t src_addr, dst_size; ++ ++ g_assert(img_comp); ++ ++ src_addr = pv_component_get_src_addr(img_comp); ++ dst_size = pv_component_get_orig_size(img_comp); ++ ++ g_assert(dst_size <= pv_component_size(img_comp)); ++ ++ switch ((PvComponentType)pv_component_type(img_comp)) { ++ case PV_COMP_TYPE_KERNEL: ++ memblob_init(&ret->kernel, src_addr, dst_size); ++ break; ++ case PV_COMP_TYPE_CMDLINE: ++ memblob_init(&ret->cmdline, src_addr, dst_size); ++ break; ++ case PV_COMP_TYPE_INITRD: ++ memblob_init(&ret->initrd, src_addr, dst_size); ++ break; ++ case PV_COMP_TYPE_STAGE3B: ++ /* nothing needs to be done since it is the ++ * stage3b itself ++ */ ++ break; ++ default: ++ g_assert_not_reached(); ++ break; ++ } ++ } ++ ++ /* for `stage3b_args` big-endian format must be used */ ++ ret->psw.mask = GUINT64_TO_BE(psw->mask); ++ ret->psw.addr = GUINT64_TO_BE(psw->addr); ++ return g_steal_pointer(&ret); ++} ++ ++gint pv_img_comps_set_offset(PvImgComps *comps, gsize offset, GError **err) ++{ ++ g_assert(IS_PAGE_ALIGNED(comps->next_src)); ++ ++ if (!IS_PAGE_ALIGNED(offset)) { ++ g_set_error(err, PV_IMAGE_ERROR, PV_IMAGE_ERROR_OFFSET, ++ _("Offset must be page aligned")); ++ return -1; ++ } ++ ++ if (pv_img_comps_length(comps) > 0) { ++ g_set_error(err, PV_IMAGE_ERROR, PV_IMAGE_ERROR_OFFSET, ++ _("Offset cannot be changed after a component was added")); ++ return -1; ++ } ++ ++ comps->next_src += offset; ++ ++ g_assert(IS_PAGE_ALIGNED(comps->next_src)); ++ return 0; ++} ++ ++GSList *pv_img_comps_get_comps(const PvImgComps *comps) ++{ ++ return comps->comps; ++} ++ ++gint pv_img_comps_finalize(PvImgComps *comps, Buffer **pld_digest, ++ Buffer **ald_digest, Buffer **tld_digest, ++ uint64_t *nep, GError **err) ++{ ++ g_autoptr(Buffer) tmp_pld_digest = NULL; ++ g_autoptr(Buffer) tmp_ald_digest = NULL; ++ g_autoptr(Buffer) tmp_tld_digest = NULL; ++ ++ comps->finalized = TRUE; ++ for (GSList *iterator = comps->comps; iterator; iterator = iterator->next) { ++ const PvComponent *comp = iterator->data; ++ ++ /* update hashes and nep */ ++ if (pv_img_comps_hash_comp(comps, comp, err) < 0) ++ return -1; ++ } ++ ++ tmp_pld_digest = digest_ctx_finalize(comps->pld, err); ++ if (!tmp_pld_digest) ++ return -1; ++ ++ tmp_ald_digest = digest_ctx_finalize(comps->ald, err); ++ if (!tmp_ald_digest) ++ return -1; ++ ++ tmp_tld_digest = digest_ctx_finalize(comps->tld, err); ++ if (!tmp_tld_digest) ++ return -1; ++ ++ *pld_digest = g_steal_pointer(&tmp_pld_digest); ++ *ald_digest = g_steal_pointer(&tmp_ald_digest); ++ *tld_digest = g_steal_pointer(&tmp_tld_digest); ++ *nep = comps->nep; ++ return 0; ++} ++ ++PvComponent *pv_img_comps_get_nth_comp(PvImgComps *comps, guint n) ++{ ++ return g_slist_nth_data(comps->comps, n); ++} +--- /dev/null ++++ b/genprotimg/src/pv/pv_comps.h +@@ -0,0 +1,42 @@ ++/* ++ * PV components related definitions and functions ++ * ++ * Copyright IBM Corp. 2020 ++ * ++ * s390-tools is free software; you can redistribute it and/or modify ++ * it under the terms of the MIT license. See LICENSE for details. ++ */ ++ ++#ifndef PV_COMPS_H ++#define PV_COMPS_H ++ ++#include ++#include ++#include ++ ++#include "boot/s390.h" ++#include "boot/stage3b.h" ++#include "utils/buffer.h" ++ ++#include "pv_comp.h" ++ ++typedef struct _pv_img_comps PvImgComps; ++ ++PvImgComps *pv_img_comps_new(const EVP_MD *ald_md, const EVP_MD *pld_md, ++ const EVP_MD *tld_md, GError **err); ++guint pv_img_comps_length(const PvImgComps *comps); ++GSList *pv_img_comps_get_comps(const PvImgComps *comps); ++struct stage3b_args *pv_img_comps_get_stage3b_args(const PvImgComps *comps, ++ struct psw_t *psw); ++gint pv_img_comps_add_component(PvImgComps *comps, PvComponent **comp, ++ GError **err); ++PvComponent *pv_img_comps_get_nth_comp(PvImgComps *comps, guint n); ++gint pv_img_comps_set_offset(PvImgComps *comps, gsize offset, GError **err); ++gint pv_img_comps_finalize(PvImgComps *comps, Buffer **pld_digest, ++ Buffer **ald_digest, Buffer **tld_digest, ++ uint64_t *nep, GError **err); ++void pv_img_comps_free(PvImgComps *comps); ++ ++WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(PvImgComps, pv_img_comps_free) ++ ++#endif +--- /dev/null ++++ b/genprotimg/src/pv/pv_error.c +@@ -0,0 +1,37 @@ ++/* ++ * PV error related functions ++ * ++ * Copyright IBM Corp. 2020 ++ * ++ * s390-tools is free software; you can redistribute it and/or modify ++ * it under the terms of the MIT license. See LICENSE for details. ++ */ ++ ++#include ++ ++#include "pv_error.h" ++ ++GQuark pv_error_quark(void) ++{ ++ return g_quark_from_static_string("pv-error-quark"); ++} ++ ++GQuark pv_crypto_error_quark(void) ++{ ++ return g_quark_from_static_string("pv-crypto-error-quark"); ++} ++ ++GQuark pv_component_error_quark(void) ++{ ++ return g_quark_from_static_string("pv-component-error-quark"); ++} ++ ++GQuark pv_image_error_quark(void) ++{ ++ return g_quark_from_static_string("pv-image-error-quark"); ++} ++ ++GQuark pv_parse_error_quark(void) ++{ ++ return g_quark_from_static_string("pv-parse-error-quark"); ++} +--- /dev/null ++++ b/genprotimg/src/pv/pv_error.h +@@ -0,0 +1,62 @@ ++/* ++ * PV error related definitions and functions ++ * ++ * Copyright IBM Corp. 2020 ++ * ++ * s390-tools is free software; you can redistribute it and/or modify ++ * it under the terms of the MIT license. See LICENSE for details. ++ */ ++ ++#ifndef PV_ERROR_H ++#define PV_ERROR_H ++ ++#include ++ ++GQuark pv_error_quark(void); ++GQuark pv_parse_error_quark(void); ++GQuark pv_component_error_quark(void); ++GQuark pv_crypto_error_quark(void); ++GQuark pv_image_error_quark(void); ++ ++#define PV_ERROR pv_error_quark() ++#define PV_PARSE_ERROR pv_parse_error_quark() ++#define PV_CRYPTO_ERROR pv_crypto_error_quark() ++#define PV_COMPONENT_ERROR pv_component_error_quark() ++#define PV_IMAGE_ERROR pv_image_error_quark() ++ ++typedef enum { ++ PV_ERROR_IPIB_SIZE, ++ PV_ERROR_PV_HDR_SIZE, ++ PV_ERROR_INTERNAL, ++} PvErrors; ++ ++typedef enum { ++ PV_PARSE_ERROR_OK = 0, ++ PV_PARSE_ERROR_SYNTAX, ++ PR_PARSE_ERROR_INVALID_ARGUMENT, ++ PR_PARSE_ERROR_MISSING_ARGUMENT, ++} PvParseErrors; ++ ++typedef enum { ++ PV_COMPONENT_ERROR_UNALIGNED, ++ PV_COMPONENT_ERROR_FINALIZED, ++} PvComponentErrors; ++ ++typedef enum { ++ PV_IMAGE_ERROR_OFFSET, ++ PV_IMAGE_ERROR_FINALIZED, ++} PvImageErrors; ++ ++typedef enum { ++ PV_CRYPTO_ERROR_VERIFICATION, ++ PV_CRYPTO_ERROR_INIT, ++ PV_CRYPTO_ERROR_READ_CERTIFICATE, ++ PV_CRYPTO_ERROR_INTERNAL, ++ PV_CRYPTO_ERROR_DERIVE, ++ PV_CRYPTO_ERROR_KEYGENERATION, ++ PV_CRYPTO_ERROR_RANDOMIZATION, ++ PV_CRYPTO_ERROR_INVALID_PARM, ++ PV_CRYPTO_ERROR_INVALID_KEY_SIZE, ++} PvCryptoErrors; ++ ++#endif +--- /dev/null ++++ b/genprotimg/src/pv/pv_hdr.c +@@ -0,0 +1,293 @@ ++/* ++ * PV header related functions ++ * ++ * Copyright IBM Corp. 2020 ++ * ++ * s390-tools is free software; you can redistribute it and/or modify ++ * it under the terms of the MIT license. See LICENSE for details. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "boot/s390.h" ++#include "include/pv_crypto_def.h" ++#include "utils/buffer.h" ++#include "utils/crypto.h" ++ ++#include "pv_comp.h" ++#include "pv_hdr.h" ++#include "pv_image.h" ++ ++void pv_hdr_free(PvHdr *hdr) ++{ ++ if (!hdr) ++ return; ++ ++ g_free(hdr->optional_items); ++ g_free(hdr->encrypted); ++ g_free(hdr->slots); ++ g_free(hdr); ++} ++ ++uint32_t pv_hdr_size(const PvHdr *hdr) ++{ ++ return GUINT32_FROM_BE(hdr->head.phs); ++} ++ ++gboolean pv_hdr_uses_encryption(const PvHdr *hdr) ++{ ++ return !(GUINT64_FROM_BE(hdr->head.pcf) & PV_CFLAG_NO_DECRYPTION); ++} ++ ++uint64_t pv_hdr_enc_size(const PvHdr *hdr) ++{ ++ return GUINT64_FROM_BE(hdr->head.sea); ++} ++ ++uint32_t pv_hdr_enc_size_casted(const PvHdr *hdr) ++{ ++ uint64_t size = pv_hdr_enc_size(hdr); ++ ++ if (size > UINT32_MAX) ++ g_abort(); ++ ++ return (uint32_t)size; ++} ++ ++static guint pv_hdr_tag_size(const PvHdr *hdr) ++{ ++ return sizeof(hdr->tag); ++} ++ ++uint32_t pv_hdr_aad_size(const PvHdr *hdr) ++{ ++ return pv_hdr_size(hdr) - pv_hdr_enc_size_casted(hdr) - ++ pv_hdr_tag_size(hdr); ++} ++ ++uint64_t pv_hdr_get_nks(const PvHdr *hdr) ++{ ++ return GUINT64_FROM_BE(hdr->head.nks); ++} ++ ++/* In-place modification of ``buf`` */ ++static gint pv_hdr_encrypt(const PvHdr *hdr, const PvImage *img, Buffer *buf, ++ GError **err) ++{ ++ uint32_t hdr_len = pv_hdr_size(hdr); ++ uint32_t aad_len = pv_hdr_aad_size(hdr); ++ guint tag_len = pv_hdr_tag_size(hdr); ++ uint32_t enc_len = pv_hdr_enc_size_casted(hdr); ++ const Buffer aad_part = { .data = buf->data, .size = aad_len }; ++ Buffer enc_part = { .data = (uint8_t *)buf->data + aad_len, ++ .size = enc_len }; ++ Buffer tag_part = { .data = (uint8_t *)buf->data + hdr_len - tag_len, ++ .size = tag_len }; ++ struct cipher_parms parms; ++ int64_t c_len; ++ ++ g_assert(aad_part.size + enc_part.size + tag_part.size == buf->size); ++ g_assert(img->cust_root_key->size <= INT_MAX); ++ g_assert(img->gcm_iv->size <= INT_MAX); ++ g_assert(EVP_CIPHER_key_length(img->gcm_cipher) == ++ (int)img->cust_root_key->size); ++ g_assert(EVP_CIPHER_iv_length(img->gcm_cipher) == (int)img->gcm_iv->size); ++ ++ parms.key = img->cust_root_key; ++ parms.iv_or_tweak = img->gcm_iv; ++ parms.cipher = img->gcm_cipher; ++ ++ /* in-place encryption */ ++ c_len = gcm_encrypt(&enc_part, &aad_part, &parms, &enc_part, &tag_part, err); ++ if (c_len < 0) ++ return -1; ++ ++ g_assert(c_len == enc_len); ++ return 0; ++} ++ ++/* Initializes the unencrypted, but integrity protected part of the PV ++ * header ++ */ ++static gint pv_hdr_aad_init(PvHdr *hdr, const PvImage *img, GError **err) ++{ ++ g_autofree union ecdh_pub_key *cust_pub_key = NULL; ++ struct pv_hdr_key_slot *hdr_slot = hdr->slots; ++ struct pv_hdr_head *head = &hdr->head; ++ g_autoptr(Buffer) pld = NULL; ++ g_autoptr(Buffer) ald = NULL; ++ g_autoptr(Buffer) tld = NULL; ++ uint64_t nep = 0; ++ ++ g_assert(sizeof(head->iv) == img->gcm_iv->size); ++ g_assert(sizeof(head->cust_pub_key) == sizeof(*cust_pub_key)); ++ ++ cust_pub_key = evp_pkey_to_ecdh_pub_key(img->cust_pub_priv_key, err); ++ if (!cust_pub_key) ++ return -1; ++ ++ head->magic = GUINT64_TO_BE(PV_MAGIC_NUMBER); ++ head->version = GUINT32_TO_BE(PV_VERSION_1); ++ /* ``phs`` is already set so we can skip it here */ ++ memcpy(head->iv, img->gcm_iv->data, sizeof(head->iv)); ++ /* ``nks`` is already set so we can skip it here */ ++ /* ``sea`` is already set so we can skip it here */ ++ head->pcf = GUINT64_TO_BE(img->pcf); ++ memcpy(head->cust_pub_key.data, cust_pub_key, ++ sizeof(head->cust_pub_key)); ++ ++ if (pv_img_calc_pld_ald_tld_nep(img, &pld, &ald, &tld, &nep, err) < 0) ++ return -1; ++ ++ g_assert(sizeof(head->pld) == pld->size); ++ g_assert(sizeof(head->ald) == ald->size); ++ g_assert(sizeof(head->tld) == tld->size); ++ ++ head->nep = GUINT64_TO_BE(nep); ++ memcpy(head->pld, pld->data, sizeof(head->pld)); ++ memcpy(head->ald, ald->data, sizeof(head->ald)); ++ memcpy(head->tld, tld->data, sizeof(head->tld)); ++ ++ /* set the key slots */ ++ for (GSList *iterator = img->key_slots; iterator; iterator = iterator->next) { ++ const PvHdrKeySlot *slot = iterator->data; ++ ++ g_assert(slot); ++ ++ /* the memory for the slots is pre-allocated so we ++ * have not to allocate and since PvHdrKeySlot is ++ * stored in the big-edian format we can simply use ++ * memcpy. ++ */ ++ memcpy(hdr_slot++, slot, sizeof(*slot)); ++ } ++ ++ return 0; ++} ++ ++/* Initializes the encrypted and also integrity protected part of the ++ * PV header ++ */ ++static gint pv_hdr_enc_init(PvHdr *hdr, const PvImage *img, GError **err) ++{ ++ struct pv_hdr_encrypted *enc = hdr->encrypted; ++ const PvComponent *stage3b; ++ struct psw_t psw; ++ ++ g_assert(sizeof(enc->img_enc_key_1) + sizeof(enc->img_enc_key_2) == ++ EVP_CIPHER_key_length(img->xts_cipher)); ++ g_assert(sizeof(enc->cust_comm_key) == img->cust_comm_key->size); ++ g_assert(img->xts_key->size == ++ (guint)EVP_CIPHER_key_length(img->xts_cipher)); ++ ++ stage3b = pv_img_get_stage3b_comp(img, err); ++ if (!stage3b) ++ return -1; ++ ++ memcpy(enc->cust_comm_key, img->cust_comm_key->data, ++ sizeof(enc->cust_comm_key)); ++ memcpy(enc->img_enc_key_1, img->xts_key->data, ++ sizeof(enc->img_enc_key_1)); ++ memcpy(enc->img_enc_key_2, ++ (uint8_t *)img->xts_key->data + sizeof(enc->img_enc_key_1), ++ sizeof(enc->img_enc_key_2)); ++ ++ /* Setup program check handler */ ++ psw.mask = GUINT64_TO_BE(DEFAULT_INITIAL_PSW_MASK); ++ psw.addr = GUINT64_TO_BE(pv_component_get_src_addr(stage3b)); ++ enc->psw = psw; ++ enc->scf = GUINT64_TO_BE(img->scf); ++ enc->noi = GUINT32_TO_BE(g_slist_length(img->optional_items)); ++ ++ /* set the optional items */ ++ for (GSList *iterator = img->optional_items; iterator; ++ iterator = iterator->next) { ++ const struct pv_hdr_opt_item *item = iterator->data; ++ ++ g_assert(item); ++ ++ /* not supported in the first version */ ++ g_assert_not_reached(); ++ } ++ ++ return 0; ++} ++ ++PvHdr *pv_hdr_new(const PvImage *img, GError **err) ++{ ++ uint32_t noi = g_slist_length(img->optional_items); ++ uint32_t hdr_size = pv_img_get_pv_hdr_size(img); ++ gsize nks = g_slist_length(img->key_slots); ++ uint32_t sea = pv_img_get_enc_size(img); ++ g_autoptr(PvHdr) ret = NULL; ++ ++ g_assert(nks > 0); ++ /* must be a multiple of AES block size */ ++ g_assert(sea % AES_BLOCK_SIZE == 0); ++ g_assert(sea >= sizeof(struct pv_hdr_encrypted)); ++ ++ ret = g_new0(PvHdr, 1); ++ ret->slots = g_new0(struct pv_hdr_key_slot, nks); ++ ret->head.phs = GUINT32_TO_BE(hdr_size); ++ ret->head.nks = GUINT64_TO_BE(nks); ++ ret->head.sea = GUINT64_TO_BE(sea); ++ ++ ret->encrypted = g_new0(struct pv_hdr_encrypted, 1); ++ ret->optional_items = g_malloc0(sea - sizeof(struct pv_hdr_encrypted)); ++ ret->encrypted->noi = GUINT32_TO_BE(noi); ++ ++ if (pv_hdr_aad_init(ret, img, err) < 0) ++ return NULL; ++ ++ if (pv_hdr_enc_init(ret, img, err) < 0) ++ return NULL; ++ ++ return g_steal_pointer(&ret); ++} ++ ++static void pv_hdr_memcpy(const PvHdr *hdr, const Buffer *dst) ++{ ++ uint64_t nks = pv_hdr_get_nks(hdr); ++ uint8_t *data; ++ ++ g_assert(dst->size == pv_hdr_size(hdr)); ++ g_assert(pv_hdr_enc_size_casted(hdr) >= sizeof(*hdr->encrypted)); ++ ++ data = memcpy(dst->data, &hdr->head, sizeof(hdr->head)); ++ data = memcpy(data + sizeof(hdr->head), hdr->slots, ++ sizeof(struct pv_hdr_key_slot) * nks); ++ data = memcpy(data + sizeof(struct pv_hdr_key_slot) * nks, ++ hdr->encrypted, sizeof(*hdr->encrypted)); ++ if (pv_hdr_enc_size_casted(hdr) - sizeof(*hdr->encrypted) > 0) { ++ (void)memcpy(data + sizeof(*hdr->encrypted), ++ hdr->optional_items, ++ pv_hdr_enc_size_casted(hdr) - sizeof(*hdr->encrypted)); ++ } ++} ++ ++Buffer *pv_hdr_serialize(const PvHdr *hdr, const PvImage *img, ++ enum PvCryptoMode mode, GError **err) ++{ ++ uint32_t hdr_size = pv_hdr_size(hdr); ++ g_autoptr(Buffer) ret = NULL; ++ ++ ret = buffer_alloc(hdr_size); ++ pv_hdr_memcpy(hdr, ret); ++ ++ if (mode == PV_ENCRYPT) { ++ /* The buffer @ret is modified in-place */ ++ if (pv_hdr_encrypt(hdr, img, ret, err) < 0) ++ return NULL; ++ } else { ++ /* Simply copy the tag */ ++ memcpy((uint8_t *)ret->data + hdr_size - pv_hdr_tag_size(hdr), ++ hdr->tag, pv_hdr_tag_size(hdr)); ++ } ++ ++ return g_steal_pointer(&ret); ++} +--- /dev/null ++++ b/genprotimg/src/pv/pv_hdr.h +@@ -0,0 +1,36 @@ ++/* ++ * PV header related functions ++ * ++ * Copyright IBM Corp. 2020 ++ * ++ * s390-tools is free software; you can redistribute it and/or modify ++ * it under the terms of the MIT license. See LICENSE for details. ++ */ ++ ++#ifndef PV_HDR_H ++#define PV_HDR_H ++ ++#include ++#include ++ ++#include "boot/s390.h" ++#include "include/pv_hdr_def.h" ++#include "utils/crypto.h" ++#include "utils/buffer.h" ++ ++#include "pv_image.h" ++ ++PvHdr *pv_hdr_new(const PvImage *img, GError **err); ++void pv_hdr_free(PvHdr *hdr); ++G_GNUC_UNUSED gboolean pv_hdr_uses_encryption(const PvHdr *hdr); ++Buffer *pv_hdr_serialize(const PvHdr *hdr, const PvImage *img, ++ enum PvCryptoMode mode, GError **err); ++uint32_t pv_hdr_size(const PvHdr *hdr); ++uint32_t pv_hdr_aad_size(const PvHdr *hdr); ++uint64_t pv_hdr_enc_size(const PvHdr *hdr); ++uint32_t pv_hdr_enc_size_casted(const PvHdr *hdr); ++uint64_t pv_hdr_get_nks(const PvHdr *hdr); ++ ++WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(PvHdr, pv_hdr_free) ++ ++#endif +--- /dev/null ++++ b/genprotimg/src/pv/pv_image.c +@@ -0,0 +1,820 @@ ++/* ++ * PV image related definitions and functions ++ * ++ * Copyright IBM Corp. 2020 ++ * ++ * s390-tools is free software; you can redistribute it and/or modify ++ * it under the terms of the MIT license. See LICENSE for details. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "boot/stage3a.h" ++#include "common.h" ++#include "include/pv_crypto_def.h" ++#include "include/pv_hdr_def.h" ++#include "utils/align.h" ++#include "utils/crypto.h" ++#include "utils/file_utils.h" ++ ++#include "pv_args.h" ++#include "pv_comps.h" ++#include "pv_error.h" ++#include "pv_hdr.h" ++#include "pv_image.h" ++#include "pv_ipib.h" ++#include "pv_opt_item.h" ++#include "pv_stage3.h" ++ ++const PvComponent *pv_img_get_stage3b_comp(const PvImage *img, GError **err) ++{ ++ const PvComponent *comp; ++ ++ g_return_val_if_fail(pv_img_comps_length(img->comps) >= 1, NULL); ++ ++ comp = pv_img_comps_get_nth_comp(img->comps, ++ pv_img_comps_length(img->comps) - 1); ++ if (!pv_component_is_stage3b(comp)) { ++ g_set_error(err, PV_ERROR, PV_ERROR_INTERNAL, ++ _("Failed to get 'stage3b' component")); ++ return NULL; ++ } ++ return comp; ++} ++ ++typedef gint (*prepare_func)(PvComponent *obj, const gchar *tmp_path, ++ void *opaque, GError **err); ++ ++static gint pv_img_prepare_component(const PvImage *img, PvComponent *comp, ++ GError **err) ++{ ++ struct cipher_parms parms = { 0 }; ++ g_autoptr(Buffer) tweak = NULL; ++ prepare_func func = NULL; ++ void *opaque = NULL; ++ gint rc; ++ ++ if (img->pcf & PV_CFLAG_NO_DECRYPTION) { ++ /* we only need to align the components */ ++ func = pv_component_align; ++ opaque = NULL; ++ } else { ++ const EVP_CIPHER *cipher = img->xts_cipher; ++ ++ g_assert_cmpint((int)img->xts_key->size, ==, ++ EVP_CIPHER_key_length(cipher)); ++ g_assert_cmpint((int)PAGE_SIZE % EVP_CIPHER_block_size(cipher), ++ ==, 0); ++ g_assert_cmpint(sizeof(comp->tweak), ==, ++ EVP_CIPHER_iv_length(cipher)); ++ g_assert(img->xts_key->size <= UINT_MAX); ++ ++ tweak = buffer_alloc(sizeof(comp->tweak.data)); ++ memcpy(tweak->data, comp->tweak.data, tweak->size); ++ func = pv_component_align_and_encrypt; ++ parms.cipher = cipher; ++ parms.key = img->xts_key; ++ parms.iv_or_tweak = tweak; ++ ++ opaque = &parms; ++ } ++ ++ rc = (*func)(comp, img->tmp_dir, opaque, err); ++ if (rc < 0) ++ return -1; ++ ++ return 0; ++} ++ ++static Buffer *pv_img_read_key(const gchar *path, guint key_size, ++ GError **err) ++{ ++ g_autoptr(Buffer) tmp_ret = NULL; ++ Buffer *ret = NULL; ++ gsize bytes_read; ++ FILE *f = NULL; ++ gsize size; ++ ++ if (file_size(path, &size, err) != 0) ++ return NULL; ++ ++ if (size - key_size != 0) { ++ g_set_error(err, PV_ERROR, PV_CRYPTO_ERROR_INVALID_KEY_SIZE, ++ _("Wrong file size '%s': read %zd, expected %u"), path, size, ++ key_size); ++ return NULL; ++ } ++ ++ f = file_open(path, "rb", err); ++ if (!f) ++ return NULL; ++ ++ tmp_ret = buffer_alloc(size); ++ if (file_read(f, tmp_ret->data, 1, tmp_ret->size, &bytes_read, err) < 0) ++ goto err; ++ ++ if (bytes_read - key_size != 0) { ++ g_set_error(err, PV_ERROR, PV_CRYPTO_ERROR_INVALID_KEY_SIZE, ++ _("Wrong file size '%s': read %zd, expected %u"), ++ path, bytes_read, key_size); ++ goto err; ++ } ++ ++ ret = g_steal_pointer(&tmp_ret); ++err: ++ if (f) ++ fclose(f); ++ return ret; ++} ++ ++static EVP_PKEY *pv_img_get_cust_pub_priv_key(gint nid, GError **err) ++{ ++ return generate_ec_key(nid, err); ++} ++ ++static HostKeyList *pv_img_get_host_keys(gchar **host_cert_paths, ++ X509_STORE *store, gint nid, ++ GError **err) ++{ ++ g_autoslist(EVP_PKEY) ret = NULL; ++ ++ g_assert(host_cert_paths); ++ ++ for (gchar **iterator = host_cert_paths; iterator != NULL && *iterator != NULL; ++ iterator++) { ++ g_autoptr(EVP_PKEY) host_key = NULL; ++ const gchar *path = *iterator; ++ ++ g_assert(path); ++ ++ host_key = read_ec_pubkey_cert(store, nid, path, err); ++ if (!host_key) ++ return NULL; ++ ++ ret = g_slist_append(ret, g_steal_pointer(&host_key)); ++ } ++ ++ return g_steal_pointer(&ret); ++} ++ ++static Buffer *pv_img_get_key(const EVP_CIPHER *cipher, const gchar *path, ++ GError **err) ++{ ++ gint key_len = EVP_CIPHER_key_length(cipher); ++ ++ g_assert(key_len > 0); ++ ++ if (path) ++ return pv_img_read_key(path, (guint)key_len, err); ++ ++ return generate_aes_key((guint)key_len, err); ++} ++ ++static Buffer *pv_img_get_iv(const EVP_CIPHER *cipher, const gchar *path, ++ GError **err) ++{ ++ gint iv_len = EVP_CIPHER_iv_length(cipher); ++ ++ g_assert(iv_len > 0); ++ ++ if (path) ++ return pv_img_read_key(path, (guint)iv_len, err); ++ ++ return generate_aes_iv((guint)iv_len, err); ++} ++ ++static int hex_str_toull(const gchar *nptr, uint64_t *dst, ++ GError **err) ++{ ++ uint64_t value; ++ gchar *end; ++ ++ g_assert(dst); ++ ++ if (!g_str_is_ascii(nptr)) { ++ g_set_error(err, PV_ERROR, EINVAL, ++ _("Invalid value: '%s'. A hexadecimal value is required, for example '0xcfe'"), ++ nptr); ++ return -1; ++ } ++ ++ value = g_ascii_strtoull(nptr, &end, 16); ++ if ((value == G_MAXUINT64 && errno == ERANGE) || ++ (end && *end != '\0')) { ++ g_set_error(err, PV_ERROR, EINVAL, ++ _("Invalid value: '%s'. A hexadecimal value is required, for example '0xcfe'"), ++ nptr); ++ return -1; ++ } ++ *dst = value; ++ return 0; ++} ++ ++static gint pv_img_set_psw_addr(PvImage *img, const gchar *psw_addr_s, ++ GError **err) ++{ ++ if (psw_addr_s) { ++ uint64_t psw_addr; ++ ++ if (hex_str_toull(psw_addr_s, &psw_addr, err) < 0) ++ return -1; ++ ++ img->initial_psw.addr = psw_addr; ++ } ++ ++ return 0; ++} ++ ++static gint pv_img_set_control_flags(PvImage *img, const gchar *pcf_s, ++ const gchar *scf_s, GError **err) ++{ ++ uint64_t flags; ++ ++ if (pcf_s) { ++ if (hex_str_toull(pcf_s, &flags, err) < 0) ++ return -1; ++ ++ img->pcf = flags; ++ } ++ ++ if (scf_s) { ++ if (hex_str_toull(scf_s, &flags, err) < 0) ++ return -1; ++ ++ img->scf = flags; ++ } ++ ++ return 0; ++} ++ ++/* read in the keys or auto-generate them */ ++static gint pv_img_set_keys(PvImage *img, const PvArgs *args, GError **err) ++{ ++ g_autoptr(X509_STORE) store = NULL; ++ ++ g_assert(img->xts_cipher); ++ g_assert(img->cust_comm_cipher); ++ g_assert(img->gcm_cipher); ++ g_assert(img->nid); ++ ++ img->xts_key = pv_img_get_key(img->xts_cipher, args->xts_key_path, err); ++ if (!img->xts_key) ++ return -1; ++ ++ img->cust_comm_key = pv_img_get_key(img->cust_comm_cipher, ++ args->cust_comm_key_path, err); ++ if (!img->cust_comm_key) ++ return -1; ++ ++ img->cust_root_key = ++ pv_img_get_key(img->gcm_cipher, args->cust_root_key_path, err); ++ if (!img->cust_root_key) ++ return -1; ++ ++ img->gcm_iv = pv_img_get_iv(img->gcm_cipher, args->gcm_iv_path, err); ++ if (!img->gcm_iv) ++ return -1; ++ ++ img->cust_pub_priv_key = pv_img_get_cust_pub_priv_key(img->nid, err); ++ if (!img->cust_pub_priv_key) ++ return -1; ++ ++ img->host_pub_keys = ++ pv_img_get_host_keys(args->host_keys, store, img->nid, err); ++ if (!img->host_pub_keys) ++ return -1; ++ ++ return 0; ++} ++ ++static void pv_img_add_host_slot(PvImage *img, PvHdrKeySlot *slot) ++{ ++ img->key_slots = g_slist_append(img->key_slots, slot); ++} ++ ++static void pv_hdr_key_slot_free(PvHdrKeySlot *slot) ++{ ++ if (!slot) ++ return; ++ ++ g_free(slot); ++} ++ ++WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(PvHdrKeySlot, pv_hdr_key_slot_free) ++ ++static PvHdrKeySlot *pv_hdr_key_slot_new(const EVP_CIPHER *gcm_cipher, ++ const Buffer *cust_root_key, ++ EVP_PKEY *cust_key, EVP_PKEY *host_key, ++ GError **err) ++{ ++ g_autoptr(PvHdrKeySlot) ret = g_new0(PvHdrKeySlot, 1); ++ g_autofree union ecdh_pub_key *pub = NULL; ++ g_autoptr(Buffer) exchange_key = NULL; ++ g_autoptr(Buffer) digest_key = NULL; ++ g_autoptr(Buffer) iv = NULL; ++ Buffer pub_buf; ++ /* No AAD data is used */ ++ Buffer aad = { .data = NULL, .size = 0 }; ++ /* Set the output buffers for the encrypted data and the ++ * generated GCM tag ++ */ ++ Buffer enc = { .data = ret->wrapped_key, .size = sizeof(ret->wrapped_key) }; ++ Buffer tag = { .data = ret->tag, .size = sizeof(ret->tag) }; ++ struct cipher_parms parms; ++ int64_t c_len = 0; ++ ++ g_assert(EVP_CIPHER_iv_length(gcm_cipher) >= 0); ++ ++ pub = evp_pkey_to_ecdh_pub_key(host_key, err); ++ if (!pub) ++ return NULL; ++ ++ pub_buf.data = pub->data; ++ pub_buf.size = sizeof(*pub); ++ digest_key = sha256_buffer(&pub_buf, err); ++ if (!digest_key) ++ return NULL; ++ ++ g_assert(digest_key->size == sizeof(ret->digest_key)); ++ /* set `digest_key` field */ ++ memcpy(ret->digest_key, digest_key->data, sizeof(ret->digest_key)); ++ ++ exchange_key = compute_exchange_key(cust_key, host_key, err); ++ if (!exchange_key) ++ return NULL; ++ ++ /* initialize cipher parameters */ ++ g_assert(exchange_key->size <= INT_MAX); ++ g_assert(exchange_key->size == (guint)EVP_CIPHER_key_length(gcm_cipher)); ++ ++ /* create zero IV */ ++ iv = buffer_alloc((guint)EVP_CIPHER_iv_length(gcm_cipher)); ++ parms.iv_or_tweak = iv; ++ parms.key = exchange_key; ++ parms.cipher = gcm_cipher; ++ ++ /* Encrypt the customer root key that is used for the encryption ++ * of the PV header ++ */ ++ c_len = gcm_encrypt(cust_root_key, &aad, &parms, &enc, &tag, err); ++ if (c_len < 0) ++ return NULL; ++ ++ g_assert(c_len == (int64_t)cust_root_key->size); ++ return g_steal_pointer(&ret); ++} ++ ++static gint pv_img_set_host_slots(PvImage *img, GError **err) ++{ ++ for (GSList *iterator = img->host_pub_keys; iterator; iterator = iterator->next) { ++ EVP_PKEY *host_key = iterator->data; ++ ++ g_assert(host_key); ++ ++ PvHdrKeySlot *slot = pv_hdr_key_slot_new(img->gcm_cipher, ++ img->cust_root_key, ++ img->cust_pub_priv_key, ++ host_key, err); ++ if (!slot) ++ return -1; ++ ++ pv_img_add_host_slot(img, slot); ++ } ++ ++ return 0; ++} ++ ++static gint pv_img_set_comps_offset(PvImage *img, uint64_t offset, GError **err) ++{ ++ return pv_img_comps_set_offset(img->comps, offset, err); ++} ++ ++PvImage *pv_img_new(PvArgs *args, const gchar *stage3a_path, GError **err) ++{ ++ g_autoptr(PvImage) ret = g_new0(PvImage, 1); ++ uint64_t offset; ++ ++ g_assert(args->tmp_dir); ++ g_assert(stage3a_path); ++ ++ if (args->no_verify) ++ g_warning(_("host-key document verification is disabled. Your workload is not secured.")); ++ ++ ret->comps = pv_img_comps_new(EVP_sha512(), EVP_sha512(), EVP_sha512(), err); ++ if (!ret->comps) ++ return NULL; ++ ++ ret->cust_comm_cipher = EVP_aes_256_gcm(); ++ ret->gcm_cipher = EVP_aes_256_gcm(); ++ ret->initial_psw.addr = DEFAULT_INITIAL_PSW_ADDR; ++ ret->initial_psw.mask = DEFAULT_INITIAL_PSW_MASK; ++ ret->nid = NID_secp521r1; ++ ret->tmp_dir = g_strdup(args->tmp_dir); ++ ret->xts_cipher = EVP_aes_256_xts(); ++ ++ /* set initial PSW that will be loaded by the stage3b */ ++ if (pv_img_set_psw_addr(ret, args->psw_addr, err) < 0) ++ return NULL; ++ ++ /* set the control flags: PCF and SCF */ ++ if (pv_img_set_control_flags(ret, args->pcf, args->scf, err) < 0) ++ return NULL; ++ ++ /* read in the keys */ ++ if (pv_img_set_keys(ret, args, err) < 0) ++ return NULL; ++ ++ if (pv_img_set_host_slots(ret, err) < 0) ++ return NULL; ++ ++ /* allocate enough memory for the stage3a args and load the ++ * stage3a template into memory and set the loader_psw ++ */ ++ if (pv_img_load_and_set_stage3a(ret, stage3a_path, err) < 0) ++ return NULL; ++ ++ offset = PAGE_ALIGN(STAGE3A_LOAD_ADDRESS + ret->stage3a->size); ++ ++ /* shift right all components by the size of stage3a loader */ ++ if (pv_img_set_comps_offset(ret, offset, err) < 0) ++ return NULL; ++ ++ return g_steal_pointer(&ret); ++} ++ ++void pv_img_free(PvImage *img) ++{ ++ if (!img) ++ return; ++ ++ g_slist_free_full(img->optional_items, ++ (GDestroyNotify)pv_opt_item_free); ++ g_slist_free_full(img->key_slots, (GDestroyNotify)pv_hdr_key_slot_free); ++ g_slist_free_full(img->host_pub_keys, (GDestroyNotify)EVP_PKEY_free); ++ EVP_PKEY_free(img->cust_pub_priv_key); ++ buffer_clear(&img->stage3a); ++ pv_img_comps_free(img->comps); ++ g_free(img->tmp_dir); ++ buffer_free(img->xts_key); ++ buffer_free(img->cust_root_key); ++ buffer_free(img->gcm_iv); ++ buffer_free(img->cust_comm_key); ++ g_free(img); ++} ++ ++static gint pv_img_prepare_and_add_component(PvImage *img, PvComponent **comp, ++ GError **err) ++{ ++ g_assert(comp); ++ g_assert(*comp); ++ ++ /* prepares the component: does the alignment and encryption ++ * if required ++ */ ++ if (pv_img_prepare_component(img, *comp, err) < 0) ++ return -1; ++ ++ /* calculates the memory layout and adds the component to its ++ * internal list ++ */ ++ if (pv_img_comps_add_component(img->comps, comp, err) < 0) ++ return -1; ++ ++ g_assert(!*comp); ++ return 0; ++} ++ ++gint pv_img_add_component(PvImage *img, const PvArg *arg, GError **err) ++{ ++ g_autoptr(PvComponent) comp = NULL; ++ ++ comp = pv_component_new_file(arg->type, arg->path, err); ++ if (!comp) ++ return -1; ++ ++ if (pv_img_prepare_and_add_component(img, &comp, err) < 0) ++ return -1; ++ ++ g_assert(!comp); ++ return 0; ++} ++ ++gint pv_img_calc_pld_ald_tld_nep(const PvImage *img, Buffer **pld, Buffer **ald, ++ Buffer **tld, uint64_t *nep, GError **err) ++{ ++ return pv_img_comps_finalize(img->comps, pld, ald, tld, nep, err); ++} ++ ++static gint pv_img_build_stage3b(PvImage *img, Buffer *stage3b, GError **err) ++{ ++ g_autofree struct stage3b_args *args = NULL; ++ ++ args = pv_img_comps_get_stage3b_args(img->comps, &img->initial_psw); ++ if (!args) { ++ g_set_error(err, PV_ERROR, PV_ERROR_INTERNAL, ++ _("Cannot generate stage3b arguments")); ++ return -1; ++ } ++ ++ build_stage3b(stage3b, args); ++ return 0; ++} ++ ++gint pv_img_add_stage3b_comp(PvImage *img, const gchar *path, GError **err) ++{ ++ g_autoptr(PvComponent) comp = NULL; ++ g_autoptr(Buffer) stage3b = NULL; ++ ++ stage3b = stage3b_getblob(path, err); ++ if (!stage3b) ++ return -1; ++ ++ /* set the stage3b data */ ++ if (pv_img_build_stage3b(img, stage3b, err) < 0) ++ return -1; ++ ++ comp = pv_component_new_buf(PV_COMP_TYPE_STAGE3B, stage3b, err); ++ if (!comp) ++ return -1; ++ ++ if (pv_img_prepare_and_add_component(img, &comp, err) < 0) ++ return -1; ++ ++ g_assert(!comp); ++ return 0; ++} ++ ++static uint32_t pv_img_get_aad_size(const PvImage *img) ++{ ++ uint32_t key_size, size = 0; ++ ++ g_assert(sizeof(struct pv_hdr_head) <= UINT32_MAX); ++ g_assert(sizeof(struct pv_hdr_key_slot) <= UINT32_MAX); ++ ++ g_assert_true(g_uint_checked_add(&size, size, ++ (uint32_t)sizeof(struct pv_hdr_head))); ++ g_assert_true(g_uint_checked_mul(&key_size, ++ (uint32_t)sizeof(struct pv_hdr_key_slot), ++ g_slist_length(img->key_slots))); ++ g_assert_true(g_uint_checked_add(&size, size, key_size)); ++ return size; ++} ++ ++static uint32_t pv_img_get_opt_items_size(const PvImage *img) ++{ ++ uint32_t ret = 0; ++ ++ g_assert(img); ++ ++ for (GSList *iterator = img->optional_items; iterator; ++ iterator = iterator->next) { ++ const struct pv_hdr_opt_item *item = iterator->data; ++ ++ g_assert(item); ++ g_assert_true(g_uint_checked_add(&ret, ret, pv_opt_item_size(item))); ++ } ++ return ret; ++} ++ ++uint32_t pv_img_get_enc_size(const PvImage *img) ++{ ++ uint32_t ret = 0; ++ ++ g_assert(sizeof(struct pv_hdr_encrypted) <= UINT32_MAX); ++ ++ g_assert_true(g_uint_checked_add( ++ &ret, ret, (uint32_t)sizeof(struct pv_hdr_encrypted))); ++ g_assert_true( ++ g_uint_checked_add(&ret, ret, pv_img_get_opt_items_size(img))); ++ return ret; ++} ++ ++static uint32_t pv_img_get_tag_size(const PvImage *img G_GNUC_UNUSED) ++{ ++ g_assert(sizeof(((struct pv_hdr *)0)->tag) <= UINT32_MAX); ++ ++ return (uint32_t)sizeof(((struct pv_hdr *)0)->tag); ++} ++ ++uint32_t pv_img_get_pv_hdr_size(const PvImage *img) ++{ ++ uint32_t size = 0; ++ ++ g_assert_true( ++ g_uint_checked_add(&size, size, pv_img_get_aad_size(img))); ++ g_assert_true( ++ g_uint_checked_add(&size, size, pv_img_get_enc_size(img))); ++ g_assert_true( ++ g_uint_checked_add(&size, size, pv_img_get_tag_size(img))); ++ return size; ++} ++ ++static gint get_stage3a_data_size(const PvImage *img, gsize *data_size, ++ GError **err) ++{ ++ gsize ipib_size, hdr_size; ++ ++ g_assert(data_size); ++ g_assert(*data_size == 0); ++ ++ ipib_size = pv_ipib_get_size(pv_img_comps_length(img->comps)); ++ if (ipib_size > PV_V1_IPIB_MAX_SIZE) { ++ g_set_error(err, PV_ERROR, PV_ERROR_IPIB_SIZE, ++ _("IPIB size is too large: '%zu' > '%zu'"), ++ ipib_size, PV_V1_IPIB_MAX_SIZE); ++ return -1; ++ } ++ ++ hdr_size = pv_img_get_pv_hdr_size(img); ++ if (hdr_size > PV_V1_PV_HDR_MAX_SIZE) { ++ g_set_error(err, PV_ERROR, PV_ERROR_PV_HDR_SIZE, ++ _("PV header size is too large: '%zu' > '%zu'"), ++ hdr_size, PV_V1_PV_HDR_MAX_SIZE); ++ return -1; ++ } ++ ++ *data_size += PAGE_ALIGN(ipib_size); ++ *data_size += PAGE_ALIGN(hdr_size); ++ return 0; ++} ++ ++gint pv_img_load_and_set_stage3a(PvImage *img, const gchar *path, GError **err) ++{ ++ g_autoptr(Buffer) stage3a = NULL; ++ gsize bin_size, data_size = 0; ++ ++ if (get_stage3a_data_size(img, &data_size, err) < 0) ++ return -1; ++ ++ stage3a = stage3a_getblob(path, &bin_size, data_size, err); ++ if (!stage3a) ++ return -1; ++ ++ img->stage3a_psw.addr = STAGE3A_ENTRY; ++ img->stage3a_psw.mask = DEFAULT_INITIAL_PSW_MASK; ++ ++ /* set addresses and size */ ++ img->stage3a = g_steal_pointer(&stage3a); ++ img->stage3a_bin_size = bin_size; ++ return 0; ++} ++ ++/* Creates the PV IPIB and sets the stage3a arguments */ ++static gint pv_img_build_stage3a(Buffer *stage3a, gsize stage3a_bin_size, ++ GSList *comps, const Buffer *hdr, GError **err) ++{ ++ g_autofree struct ipl_parameter_block *ipib = NULL; ++ ++ g_assert(stage3a); ++ g_assert(hdr); ++ ++ ipib = pv_ipib_new(comps, hdr, err); ++ if (!ipib) ++ return -1; ++ ++ if (build_stage3a(stage3a, stage3a_bin_size, hdr, ipib, err) < 0) ++ return -1; ++ ++ g_info("%12s:\t0x%012lx (%12ld / %12ld Bytes)", "stage3a", ++ STAGE3A_LOAD_ADDRESS, stage3a->size, stage3a->size); ++ return 0; ++} ++ ++/* Creates the actual PV header (serialized and AES-GCM encrypted) */ ++static Buffer *pv_img_create_pv_hdr(PvImage *img, GError **err) ++{ ++ g_autoptr(Buffer) hdr_buf = NULL; ++ g_autoptr(PvHdr) hdr = NULL; ++ ++ hdr = pv_hdr_new(img, err); ++ if (!hdr) ++ return NULL; ++ ++ hdr_buf = pv_hdr_serialize(hdr, img, PV_ENCRYPT, err); ++ if (!hdr_buf) ++ return NULL; ++ ++ return g_steal_pointer(&hdr_buf); ++} ++ ++/* No changes to the components are allowed after calling this ++ * function ++ */ ++gint pv_img_finalize(PvImage *pv, const gchar *stage3b_path, GError **err) ++{ ++ g_autoptr(Buffer) hdr = NULL; ++ ++ /* load stage3b template into memory and add it to the list of ++ * components. This must be done before calling ++ * `pv_img_load_and_set_stage3a`. ++ */ ++ if (pv_img_add_stage3b_comp(pv, stage3b_path, err) < 0) ++ return -1; ++ ++ /* create the PV header */ ++ hdr = pv_img_create_pv_hdr(pv, err); ++ if (!hdr) ++ return -1; ++ ++ /* generate stage3a. At this point in time the PV header and ++ * the stage3b must be generated and encrypted ++ */ ++ if (pv_img_build_stage3a(pv->stage3a, pv->stage3a_bin_size, ++ pv_img_comps_get_comps(pv->comps), hdr, err) < 0) ++ return -1; ++ ++ return 0; ++} ++ ++static gint convert_psw_to_short_psw(const struct psw_t *psw, uint64_t *dst, ++ GError **err) ++{ ++ g_assert(psw); ++ g_assert(dst); ++ ++ uint64_t psw_addr = psw->addr; ++ uint64_t psw_mask = psw->mask; ++ ++ /* test if PSW mask can be converted */ ++ if (psw_mask & PSW_SHORT_ADDR_MASK) { ++ g_set_error(err, PV_ERROR, PV_ERROR_INTERNAL, ++ _("Failed to convert PSW to short PSW")); ++ return -1; ++ } ++ ++ /* test for bit 12 */ ++ if (psw_mask & PSW_MASK_BIT_12) { ++ g_set_error(err, PV_ERROR, PV_ERROR_INTERNAL, ++ _("Failed to convert PSW to short PSW")); ++ return -1; ++ } ++ ++ /* test if PSW addr can be converted */ ++ if (psw_addr & ~PSW_SHORT_ADDR_MASK) { ++ g_set_error(err, PV_ERROR, PV_ERROR_INTERNAL, ++ _("Failed to convert PSW to short PSW")); ++ return -1; ++ } ++ ++ *dst = psw_mask; ++ /* set bit 12 to 1 */ ++ *dst |= PSW_MASK_BIT_12; ++ *dst |= psw_addr; ++ return 0; ++} ++ ++static gint write_short_psw(FILE *f, struct psw_t *psw, GError **err) ++{ ++ uint64_t short_psw, short_psw_be; ++ ++ if (convert_psw_to_short_psw(psw, &short_psw, err) < 0) ++ return -1; ++ ++ short_psw_be = GUINT64_TO_BE(short_psw); ++ return file_write(f, &short_psw_be, 1, sizeof(short_psw_be), NULL, err); ++} ++ ++gint pv_img_write(PvImage *img, const gchar *path, GError **err) ++{ ++ gint ret = -1; ++ FILE *f = file_open(path, "wb", err); ++ ++ if (!f) ++ return -1; ++ ++ if (write_short_psw(f, &img->stage3a_psw, err) < 0) { ++ g_prefix_error(err, _("Failed to write image '%s': "), path); ++ goto err; ++ } ++ ++ if (seek_and_write_buffer(f, img->stage3a, STAGE3A_LOAD_ADDRESS, err) < ++ 0) { ++ g_prefix_error(err, _("Failed to write image '%s': "), path); ++ goto err; ++ } ++ ++ /* list is sorted by component type => by address */ ++ for (GSList *iterator = pv_img_comps_get_comps(img->comps); iterator; ++ iterator = iterator->next) { ++ gint rc; ++ const PvComponent *comp = iterator->data; ++ ++ rc = pv_component_write(comp, f, err); ++ if (rc < 0) { ++ g_prefix_error(err, _("Failed to write image '%s': "), ++ path); ++ goto err; ++ } ++ } ++ ++ ret = 0; ++err: ++ if (f) ++ fclose(f); ++ return ret; ++} +--- /dev/null ++++ b/genprotimg/src/pv/pv_image.h +@@ -0,0 +1,68 @@ ++/* ++ * PV image related definitions and functions ++ * ++ * Copyright IBM Corp. 2020 ++ * ++ * s390-tools is free software; you can redistribute it and/or modify ++ * it under the terms of the MIT license. See LICENSE for details. ++ */ ++ ++#ifndef PV_IMAGE_H ++#define PV_IMAGE_H ++ ++#include ++#include ++#include ++#include ++ ++#include "boot/s390.h" ++#include "utils/buffer.h" ++ ++#include "pv_args.h" ++#include "pv_comp.h" ++#include "pv_comps.h" ++#include "pv_stage3.h" ++ ++typedef struct { ++ gchar *tmp_dir; /* directory used for temporary files */ ++ Buffer *stage3a; /* stage3a containing IPIB and PV header */ ++ gsize stage3a_bin_size; /* size of stage3a.bin */ ++ struct psw_t stage3a_psw; /* (short) PSW that is written to ++ * location 0 of the created image ++ */ ++ struct psw_t initial_psw; /* PSW loaded by stage3b */ ++ EVP_PKEY *cust_pub_priv_key; /* customer private/public key */ ++ GSList *host_pub_keys; /* public host keys */ ++ gint nid; /* Elliptic Curve used for the key derivation */ ++ /* keys and cipher used for the AES-GCM encryption */ ++ Buffer *cust_root_key; ++ Buffer *gcm_iv; ++ const EVP_CIPHER *gcm_cipher; ++ /* Information for the IPIB and PV header */ ++ uint64_t pcf; ++ uint64_t scf; ++ Buffer *cust_comm_key; ++ const EVP_CIPHER *cust_comm_cipher; ++ Buffer *xts_key; ++ const EVP_CIPHER *xts_cipher; ++ GSList *key_slots; ++ GSList *optional_items; ++ PvImgComps *comps; ++} PvImage; ++ ++PvImage *pv_img_new(PvArgs *args, const gchar *stage3a_path, GError **err); ++void pv_img_free(PvImage *img); ++gint pv_img_add_component(PvImage *img, const PvArg *arg, GError **err); ++gint pv_img_finalize(PvImage *img, const gchar *stage3b_path, GError **err); ++gint pv_img_calc_pld_ald_tld_nep(const PvImage *img, Buffer **pld, Buffer **ald, ++ Buffer **tld, uint64_t *nep, GError **err); ++gint pv_img_load_and_set_stage3a(PvImage *img, const gchar *path, GError **err); ++const PvComponent *pv_img_get_stage3b_comp(const PvImage *img, GError **err); ++gint pv_img_add_stage3b_comp(PvImage *img, const gchar *path, GError **err); ++uint32_t pv_img_get_enc_size(const PvImage *img); ++uint32_t pv_img_get_pv_hdr_size(const PvImage *img); ++gint pv_img_write(PvImage *img, const gchar *path, GError **err); ++ ++G_DEFINE_AUTOPTR_CLEANUP_FUNC(PvImage, pv_img_free) ++ ++#endif +--- /dev/null ++++ b/genprotimg/src/pv/pv_ipib.c +@@ -0,0 +1,128 @@ ++/* ++ * PV IPIB related definitions and functions ++ * ++ * Copyright IBM Corp. 2020 ++ * ++ * s390-tools is free software; you can redistribute it and/or modify ++ * it under the terms of the MIT license. See LICENSE for details. ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include "boot/ipl.h" ++#include "boot/s390.h" ++#include "common.h" ++#include "include/pv_hdr_def.h" ++#include "lib/zt_common.h" ++#include "utils/align.h" ++#include "utils/buffer.h" ++ ++#include "pv_comp.h" ++#include "pv_error.h" ++#include "pv_ipib.h" ++ ++uint64_t pv_ipib_get_size(uint32_t num_comp) ++{ ++ gsize ipib_size = sizeof(struct ipl_pl_hdr) + ++ sizeof(struct ipl_pb0_pv) + ++ num_comp * sizeof(struct ipl_pb0_pv_comp); ++ ++ /* the minimal size is one page */ ++ return MAX(ipib_size, PAGE_SIZE); ++} ++ ++static gint pv_ipib_init(IplParameterBlock *ipib, GSList *comps, ++ const Buffer *hdr) ++{ ++ g_assert(sizeof(struct ipl_pl_hdr) <= UINT32_MAX); ++ g_assert(sizeof(struct ipl_pb0_pv_comp) <= UINT32_MAX); ++ g_assert(sizeof(struct ipl_pb0_pv) <= UINT32_MAX); ++ g_assert(ipib); ++ ++ guint comps_length = g_slist_length(comps); ++ uint32_t ipl_pl_hdr_size = (uint32_t)sizeof(struct ipl_pl_hdr); ++ struct ipl_pb0_pv *pv = &ipib->pv; ++ uint32_t ipib_comps_size; ++ uint32_t blk0_len; ++ uint32_t ipib_size; ++ gsize i; ++ ++ g_assert_true( ++ g_uint_checked_mul(&ipib_comps_size, comps_length, ++ (uint32_t)sizeof(struct ipl_pb0_pv_comp))); ++ g_assert_true(g_uint_checked_add(&blk0_len, (uint32_t)sizeof(*pv), ++ ipib_comps_size)); ++ g_assert(ipl_pl_hdr_size + blk0_len <= PAGE_SIZE); ++ ++ ipib_size = MAX(ipl_pl_hdr_size + blk0_len, (uint32_t)PAGE_SIZE); ++ g_assert(pv_ipib_get_size(comps_length) == ipib_size); ++ ++ pv->pbt = IPL_TYPE_PV; ++ pv->len = GUINT32_TO_BE(blk0_len); ++ pv->num_comp = GUINT32_TO_BE(comps_length); ++ /* both values will be overwritten during the IPL process by ++ * the stage3a loader ++ */ ++ pv->pv_hdr_addr = GUINT64_TO_BE(0x0); ++ pv->pv_hdr_size = GUINT64_TO_BE(hdr->size); ++ ++ ipib->hdr.len = GUINT32_TO_BE(ipib_size); ++ ipib->hdr.version = IPL_PARM_BLOCK_VERSION; ++ ++ i = 0; ++ for (GSList *iterator = comps; iterator; iterator = iterator->next, i++) { ++ const PvComponent *comp = iterator->data; ++ uint64_t comp_addr, comp_size; ++ ++ g_assert(comp); ++ ++ comp_addr = pv_component_get_src_addr(comp); ++ comp_size = pv_component_size(comp); ++ ++ g_assert(IS_PAGE_ALIGNED(comp_size)); ++ ++ pv->components[i].addr = GUINT64_TO_BE(comp_addr); ++ pv->components[i].len = GUINT64_TO_BE(comp_size); ++ pv->components[i].tweak_pref = ++ GUINT64_TO_BE(pv_component_get_tweak_prefix(comp)); ++ if (i > 0) { ++ /* tweak prefixes of the components must grow ++ * strictly monotonous ++ */ ++ g_assert(GUINT64_FROM_BE(pv->components[i].tweak_pref) > ++ GUINT64_FROM_BE(pv->components[i - 1].tweak_pref)); ++ } ++ } ++ ++ return 0; ++} ++ ++IplParameterBlock *pv_ipib_new(GSList *comps, const Buffer *hdr, GError **err) ++{ ++ uint64_t ipib_size = pv_ipib_get_size(g_slist_length(comps)); ++ g_autoptr(IplParameterBlock) ret = NULL; ++ ++ if (ipib_size > PV_V1_IPIB_MAX_SIZE) { ++ g_set_error(err, PV_ERROR, PV_ERROR_IPIB_SIZE, ++ _("IPIB size is too large: %lu < %lu"), ipib_size, ++ PAGE_SIZE); ++ return NULL; ++ } ++ ++ ret = g_malloc0(ipib_size); ++ if (pv_ipib_init(ret, comps, hdr) < 0) ++ return NULL; ++ ++ return g_steal_pointer(&ret); ++} ++ ++void pv_ipib_free(IplParameterBlock *ipib) ++{ ++ if (!ipib) ++ return; ++ ++ g_free(ipib); ++} +--- /dev/null ++++ b/genprotimg/src/pv/pv_ipib.h +@@ -0,0 +1,27 @@ ++/* ++ * PV IPIB related definitions and functions ++ * ++ * Copyright IBM Corp. 2020 ++ * ++ * s390-tools is free software; you can redistribute it and/or modify ++ * it under the terms of the MIT license. See LICENSE for details. ++ */ ++ ++#ifndef PV_IPIB_H ++#define PV_IPIB_H ++ ++#include ++#include ++ ++#include "boot/ipl.h" ++#include "utils/buffer.h" ++ ++typedef struct ipl_parameter_block IplParameterBlock; ++ ++uint64_t pv_ipib_get_size(uint32_t num_comp); ++IplParameterBlock *pv_ipib_new(GSList *comps, const Buffer *hdr, GError **err); ++void pv_ipib_free(IplParameterBlock *ipib); ++ ++WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(IplParameterBlock, pv_ipib_free) ++ ++#endif +--- /dev/null ++++ b/genprotimg/src/pv/pv_opt_item.c +@@ -0,0 +1,26 @@ ++/* ++ * PV optional item related definitions and functions ++ * ++ * Copyright IBM Corp. 2020 ++ * ++ * s390-tools is free software; you can redistribute it and/or modify ++ * it under the terms of the MIT license. See LICENSE for details. ++ */ ++ ++#include ++ ++#include "pv_opt_item.h" ++ ++uint32_t pv_opt_item_size(const struct pv_hdr_opt_item *item G_GNUC_UNUSED) ++{ ++ /* not implemented yet */ ++ g_assert_not_reached(); ++} ++ ++void pv_opt_item_free(struct pv_hdr_opt_item *item) ++{ ++ if (!item) ++ return; ++ ++ g_free(item); ++} +--- /dev/null ++++ b/genprotimg/src/pv/pv_opt_item.h +@@ -0,0 +1,20 @@ ++/* ++ * PV optional item related definitions and functions ++ * ++ * Copyright IBM Corp. 2020 ++ * ++ * s390-tools is free software; you can redistribute it and/or modify ++ * it under the terms of the MIT license. See LICENSE for details. ++ */ ++ ++#ifndef PV_OPT_ITEM_H ++#define PV_OPT_ITEM_H ++ ++#include ++ ++#include "include/pv_hdr_def.h" ++ ++uint32_t pv_opt_item_size(const struct pv_hdr_opt_item *item); ++void pv_opt_item_free(struct pv_hdr_opt_item *item); ++ ++#endif +--- /dev/null ++++ b/genprotimg/src/pv/pv_stage3.c +@@ -0,0 +1,164 @@ ++/* ++ * PV stage3 loader related definitions and functions ++ * ++ * Copyright IBM Corp. 2020 ++ * ++ * s390-tools is free software; you can redistribute it and/or modify ++ * it under the terms of the MIT license. See LICENSE for details. ++ */ ++ ++#include ++#include ++#include ++ ++#include "boot/ipl.h" ++#include "boot/stage3a.h" ++#include "boot/stage3b.h" ++#include "common.h" ++#include "utils/align.h" ++ ++#include "pv_error.h" ++#include "pv_stage3.h" ++ ++#define STAGE3A_ARGS(data_ptr, loader_size) \ ++ ((struct stage3a_args *)((uint64_t)data_ptr + loader_size - \ ++ sizeof(struct stage3a_args))) ++ ++static Buffer *loader_getblob(const gchar *filename, gsize *loader_size, ++ gsize args_size, gsize data_size, ++ gboolean data_aligned, GError **err) ++{ ++ g_autoptr(GMappedFile) mapped_file = NULL; ++ g_autoptr(Buffer) ret = NULL; ++ gsize size, tmp_loader_size; ++ gchar *loader_data; ++ ++ g_assert(loader_size); ++ ++ mapped_file = g_mapped_file_new(filename, FALSE, err); ++ if (!mapped_file) ++ return NULL; ++ ++ loader_data = g_mapped_file_get_contents(mapped_file); ++ if (!loader_data) { ++ g_set_error(err, G_FILE_ERROR, G_FILE_ERROR_BADF, ++ _("File '%s' is empty"), filename); ++ return NULL; ++ } ++ tmp_loader_size = g_mapped_file_get_length(mapped_file); ++ ++ if (tmp_loader_size < args_size) { ++ g_set_error(err, G_FILE_ERROR, G_FILE_ERROR_BADF, ++ _("File size less than expected: %lu < %ln"), ++ tmp_loader_size, loader_size); ++ return NULL; ++ } ++ ++ /* For example, the PV header and IPIB data must be page ++ * aligned. ++ */ ++ size = (data_aligned ? PAGE_ALIGN(tmp_loader_size) : tmp_loader_size) + ++ data_size; ++ ++ ret = buffer_alloc(size); ++ ++ /* copy the loader "template" */ ++ memcpy(ret->data, loader_data, tmp_loader_size); ++ /* reset our dummy data (offsets and length) to zeros */ ++ memset((uint8_t *)ret->data + tmp_loader_size - args_size, 0, ++ args_size); ++ *loader_size = tmp_loader_size; ++ return g_steal_pointer(&ret); ++} ++ ++Buffer *stage3a_getblob(const gchar *filename, gsize *loader_size, ++ gsize data_size, GError **err) ++{ ++ return loader_getblob(filename, loader_size, ++ sizeof(struct stage3a_args), data_size, TRUE, ++ err); ++} ++ ++/* For the memory layout see stage3a.lds */ ++/* Set the right offsets and sizes in the stage3a template + add ++ * the IPIB block with the PV header ++ */ ++static gint stage3a_set_data(Buffer *loader, gsize loader_size, ++ const Buffer *hdr, struct ipl_parameter_block *ipib, ++ GError **err) ++{ ++ uint32_t ipib_size = GUINT32_FROM_BE(ipib->hdr.len); ++ gsize args_size = sizeof(struct stage3a_args); ++ uint32_t hdr_size = (uint32_t)hdr->size; ++ uint64_t args_addr, next_data_addr; ++ ++ if (hdr->size > UINT32_MAX) { ++ g_set_error(err, PV_ERROR, PV_ERROR_INTERNAL, ++ _("Invalid header size: %zu"), hdr->size); ++ return -1; ++ } ++ ++ /* we assume here that the loader ``stage3a`` is loaded page ++ * aligned in the guest ++ */ ++ args_addr = (uint64_t)loader->data + loader_size - args_size; ++ ++ /* therefore `next_data_addr` is also page aligned */ ++ next_data_addr = (uint64_t)loader->data + PAGE_ALIGN(loader_size); ++ ++ /* copy IPIB data */ ++ memcpy((void *)next_data_addr, ipib, ipib_size); ++ ++ /* set IPIB offset in relation to the stage3a arguments */ ++ STAGE3A_ARGS(loader->data, loader_size)->ipib_offs = ++ GUINT64_TO_BE(next_data_addr - args_addr); ++ ++ next_data_addr = next_data_addr + PAGE_ALIGN(ipib_size); ++ /* copy PV header */ ++ memcpy((void *)next_data_addr, hdr->data, hdr_size); ++ /* set PV header size and offset in relation to the stage3a ++ * arguments ++ */ ++ STAGE3A_ARGS(loader->data, loader_size)->hdr_offs = ++ GUINT64_TO_BE(next_data_addr - args_addr); ++ STAGE3A_ARGS(loader->data, loader_size)->hdr_size = GUINT64_TO_BE(hdr_size); ++ ++ return 0; ++} ++ ++gint build_stage3a(Buffer *loader, gsize loader_size, const Buffer *hdr, ++ struct ipl_parameter_block *ipib, GError **err) ++{ ++ return stage3a_set_data(loader, loader_size, hdr, ipib, err); ++} ++ ++Buffer *stage3b_getblob(const gchar *filename, GError **err) ++{ ++ g_autoptr(Buffer) ret = NULL; ++ gsize rb_size; ++ ++ ret = loader_getblob(filename, &rb_size, sizeof(struct stage3b_args), 0, ++ FALSE, err); ++ if (!ret) ++ return NULL; ++ ++ g_assert(ret->size == rb_size); ++ return g_steal_pointer(&ret); ++} ++ ++void build_stage3b(Buffer *stage3b, const struct stage3b_args *args) ++{ ++ g_assert(stage3b->size > sizeof(*args)); ++ ++ /* at the end of the stage3b there are the stage3b args ++ * positioned ++ */ ++ memcpy((uint8_t *)stage3b->data + stage3b->size - sizeof(*args), args, ++ sizeof(*args)); ++} ++ ++void memblob_init(struct memblob *arg, uint64_t src, uint64_t size) ++{ ++ arg->src = GUINT64_TO_BE(src); ++ arg->size = GUINT64_TO_BE(size); ++} +--- /dev/null ++++ b/genprotimg/src/pv/pv_stage3.h +@@ -0,0 +1,30 @@ ++/* ++ * PV stage3 loader related definitions and functions ++ * ++ * Copyright IBM Corp. 2020 ++ * ++ * s390-tools is free software; you can redistribute it and/or modify ++ * it under the terms of the MIT license. See LICENSE for details. ++ */ ++ ++#ifndef PV_STAGE3_H ++#define PV_STAGE3_H ++ ++#include ++#include ++#include ++ ++#include "boot/ipl.h" ++#include "boot/s390.h" ++#include "boot/stage3b.h" ++#include "utils/buffer.h" ++ ++Buffer *stage3a_getblob(const gchar *filename, gsize *loader_size, ++ gsize data_size, GError **err); ++gint build_stage3a(Buffer *dc, gsize dc_size, const Buffer *hdr, ++ struct ipl_parameter_block *ipib, GError **err); ++Buffer *stage3b_getblob(const gchar *filename, GError **err); ++void build_stage3b(Buffer *stage3b, const struct stage3b_args *args); ++void memblob_init(struct memblob *arg, uint64_t src, uint64_t size); ++ ++#endif +--- /dev/null ++++ b/genprotimg/src/utils/align.h +@@ -0,0 +1,24 @@ ++/* ++ * Alignment utils ++ * ++ * Copyright IBM Corp. 2020 ++ * ++ * s390-tools is free software; you can redistribute it and/or modify ++ * it under the terms of the MIT license. See LICENSE for details. ++ */ ++ ++#ifndef PV_UTILS_ALIGN_H ++#define PV_UTILS_ALIGN_H ++ ++#include "boot/s390.h" ++#include "lib/zt_common.h" ++ ++#define IS_ALIGNED(addr, size) (!(addr & (size - 1))) ++ ++/* align addr to the next page boundary */ ++#define PAGE_ALIGN(addr) ALIGN((unsigned long)addr, PAGE_SIZE) ++ ++/* test whether an address is aligned to PAGE_SIZE or not */ ++#define IS_PAGE_ALIGNED(addr) IS_ALIGNED((unsigned long)(addr), PAGE_SIZE) ++ ++#endif +--- /dev/null ++++ b/genprotimg/src/utils/buffer.c +@@ -0,0 +1,69 @@ ++/* ++ * Buffer functions ++ * ++ * Copyright IBM Corp. 2020 ++ * ++ * s390-tools is free software; you can redistribute it and/or modify ++ * it under the terms of the MIT license. See LICENSE for details. ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include "align.h" ++#include "buffer.h" ++#include "common.h" ++#include "file_utils.h" ++ ++Buffer *buffer_alloc(gsize size) ++{ ++ Buffer *ret = g_new0(Buffer, 1); ++ ++ ret->data = g_malloc0(size); ++ ret->size = size; ++ return ret; ++} ++ ++Buffer *buffer_dup(const Buffer *buf, gboolean page_aligned) ++{ ++ Buffer *ret; ++ gsize size; ++ ++ if (!buf) ++ return NULL; ++ ++ size = buf->size; ++ if (page_aligned) ++ size = PAGE_ALIGN(size); ++ ++ ret = buffer_alloc(size); ++ ++ /* content will be 0-right-padded */ ++ memcpy(ret->data, buf->data, buf->size); ++ return ret; ++} ++ ++gint buffer_write(const Buffer *buf, FILE *file, GError **err) ++{ ++ return file_write(file, buf->data, buf->size, 1, NULL, err); ++} ++ ++void buffer_free(Buffer *buf) ++{ ++ if (!buf) ++ return; ++ ++ g_free(buf->data); ++ g_free(buf); ++} ++ ++void buffer_clear(Buffer **buf) ++{ ++ if (!buf || !*buf) ++ return; ++ ++ buffer_free(*buf); ++ *buf = NULL; ++} +--- /dev/null ++++ b/genprotimg/src/utils/buffer.h +@@ -0,0 +1,31 @@ ++/* ++ * Buffer definition and functions ++ * ++ * Copyright IBM Corp. 2020 ++ * ++ * s390-tools is free software; you can redistribute it and/or modify ++ * it under the terms of the MIT license. See LICENSE for details. ++ */ ++ ++#ifndef PV_UTILS_BUFFER_H ++#define PV_UTILS_BUFFER_H ++ ++#include ++#include ++ ++#include "common.h" ++ ++typedef struct Buffer { ++ void *data; ++ gsize size; /* in bytes */ ++} Buffer; ++ ++Buffer *buffer_alloc(gsize size); ++void buffer_free(Buffer *buf); ++void buffer_clear(Buffer **buf); ++gint buffer_write(const Buffer *buf, FILE *file, GError **err); ++Buffer *buffer_dup(const Buffer *buf, gboolean page_aligned); ++ ++WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(Buffer, buffer_free) ++ ++#endif +--- /dev/null ++++ b/genprotimg/src/utils/crypto.c +@@ -0,0 +1,798 @@ ++/* ++ * General cryptography helper functions ++ * ++ * Copyright IBM Corp. 2020 ++ * ++ * s390-tools is free software; you can redistribute it and/or modify ++ * it under the terms of the MIT license. See LICENSE for details. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "boot/s390.h" ++#include "common.h" ++#include "include/pv_crypto_def.h" ++#include "pv/pv_error.h" ++ ++#include "buffer.h" ++#include "crypto.h" ++ ++EVP_MD_CTX *digest_ctx_new(const EVP_MD *md, GError **err) ++{ ++ g_autoptr(EVP_MD_CTX) ctx = EVP_MD_CTX_new(); ++ ++ if (!ctx) ++ g_abort(); ++ ++ if (EVP_DigestInit_ex(ctx, md, NULL) != 1) { ++ g_set_error(err, PV_CRYPTO_ERROR, PV_CRYPTO_ERROR_INTERNAL, ++ _("EVP_DigestInit_ex failed")); ++ return NULL; ++ } ++ ++ return g_steal_pointer(&ctx); ++} ++ ++Buffer *digest_ctx_finalize(EVP_MD_CTX *ctx, GError **err) ++{ ++ gint md_size = EVP_MD_size(EVP_MD_CTX_md(ctx)); ++ g_autoptr(Buffer) ret = NULL; ++ guint digest_size; ++ ++ g_assert(md_size > 0); ++ ++ ret = buffer_alloc((guint)md_size); ++ if (EVP_DigestFinal_ex(ctx, ret->data, &digest_size) != 1) { ++ g_set_error(err, PV_CRYPTO_ERROR, PV_CRYPTO_ERROR_INTERNAL, ++ _("EVP_DigestFinal_ex failed")); ++ return NULL; ++ } ++ ++ g_assert(digest_size == (guint)md_size); ++ g_assert(digest_size == ret->size); ++ return g_steal_pointer(&ret); ++} ++ ++/* Returns the digest of @buf using the hash algorithm @md */ ++static Buffer *digest_buffer(const EVP_MD *md, const Buffer *buf, GError **err) ++{ ++ g_autoptr(EVP_MD_CTX) md_ctx = NULL; ++ g_autoptr(Buffer) ret = NULL; ++ g_assert(buf); ++ ++ md_ctx = digest_ctx_new(md, err); ++ if (!md_ctx) ++ return NULL; ++ ++ if (EVP_DigestUpdate(md_ctx, buf->data, buf->size) != 1) { ++ g_set_error(err, PV_CRYPTO_ERROR, PV_CRYPTO_ERROR_INTERNAL, ++ _("EVP_DigestUpdate failed")); ++ return NULL; ++ } ++ ++ ret = digest_ctx_finalize(md_ctx, err); ++ if (!ret) ++ return NULL; ++ ++ return g_steal_pointer(&ret); ++} ++ ++/* Returns the SHA256 digest of @buf */ ++Buffer *sha256_buffer(const Buffer *buf, GError **err) ++{ ++ g_autoptr(Buffer) ret = NULL; ++ ++ ret = digest_buffer(EVP_sha256(), buf, err); ++ if (!ret) ++ return NULL; ++ ++ g_assert(ret->size == SHA256_DIGEST_LENGTH); ++ return g_steal_pointer(&ret); ++} ++ ++/* Convert a EVP_PKEY to the key format used in the PV header */ ++union ecdh_pub_key *evp_pkey_to_ecdh_pub_key(EVP_PKEY *key, GError **err) ++{ ++ g_autofree union ecdh_pub_key *ret = g_new0(union ecdh_pub_key, 1); ++ g_autoptr(BIGNUM) pub_x_big = NULL; ++ g_autoptr(BIGNUM) pub_y_big = NULL; ++ g_autoptr(EC_KEY) ec_key = NULL; ++ const EC_POINT *pub_key; ++ const EC_GROUP *grp; ++ ++ ec_key = EVP_PKEY_get1_EC_KEY(key); ++ if (!ec_key) { ++ g_set_error(err, PV_CRYPTO_ERROR, PV_CRYPTO_ERROR_INTERNAL, ++ _("Key has the wrong type")); ++ return NULL; ++ } ++ ++ pub_key = EC_KEY_get0_public_key(ec_key); ++ if (!pub_key) { ++ g_set_error(err, PV_CRYPTO_ERROR, PV_CRYPTO_ERROR_INTERNAL, ++ _("Failed to get public key")); ++ return NULL; ++ } ++ ++ grp = EC_KEY_get0_group(ec_key); ++ if (!grp) { ++ g_set_error(err, PV_CRYPTO_ERROR, PV_CRYPTO_ERROR_INTERNAL, ++ _("Failed to get EC group")); ++ return NULL; ++ } ++ ++ pub_x_big = BN_new(); ++ if (!pub_x_big) ++ g_abort(); ++ ++ pub_y_big = BN_new(); ++ if (!pub_y_big) ++ g_abort(); ++ ++ if (EC_POINT_get_affine_coordinates_GFp(grp, pub_key, pub_x_big, ++ pub_y_big, NULL) != 1) { ++ g_set_error(err, PV_CRYPTO_ERROR, PV_CRYPTO_ERROR_INTERNAL, ++ _("Cannot convert key to internal format")); ++ return NULL; ++ } ++ ++ if (BN_bn2binpad(pub_x_big, ret->x, sizeof(ret->x)) < 0) { ++ g_set_error(err, PV_CRYPTO_ERROR, PV_CRYPTO_ERROR_INTERNAL, ++ _("Cannot convert key to internal format")); ++ return NULL; ++ } ++ ++ if (BN_bn2binpad(pub_y_big, ret->y, sizeof(ret->y)) < 0) { ++ g_set_error(err, PV_CRYPTO_ERROR, PV_CRYPTO_ERROR_INTERNAL, ++ _("Cannot convert key to internal format")); ++ return NULL; ++ } ++ ++ return g_steal_pointer(&ret); ++} ++ ++static Buffer *derive_key(EVP_PKEY *cust, EVP_PKEY *host, GError **err) ++{ ++ g_autoptr(EVP_PKEY_CTX) ctx = NULL; ++ g_autoptr(Buffer) ret = NULL; ++ gsize key_size; ++ ++ ctx = EVP_PKEY_CTX_new(cust, NULL); ++ if (!ctx) ++ g_abort(); ++ ++ if (EVP_PKEY_derive_init(ctx) != 1) { ++ g_set_error(err, PV_CRYPTO_ERROR, PV_CRYPTO_ERROR_INTERNAL, ++ _("Key derivation failed")); ++ return NULL; ++ } ++ ++ if (EVP_PKEY_derive_set_peer(ctx, host) != 1) { ++ g_set_error(err, PV_CRYPTO_ERROR, PV_CRYPTO_ERROR_INTERNAL, ++ _("Key derivation failed")); ++ return NULL; ++ } ++ ++ /* Determine buffer length */ ++ if (EVP_PKEY_derive(ctx, NULL, &key_size) != 1) { ++ g_set_error(err, PV_CRYPTO_ERROR, PV_CRYPTO_ERROR_DERIVE, ++ _("Key derivation failed")); ++ return NULL; ++ } ++ ++ ret = buffer_alloc(key_size); ++ if (EVP_PKEY_derive(ctx, ret->data, &key_size) != 1) { ++ g_set_error(err, PV_CRYPTO_ERROR, PV_CRYPTO_ERROR_DERIVE, ++ _("Key derivation failed")); ++ return NULL; ++ } ++ ++ g_assert(ret->size == key_size); ++ return g_steal_pointer(&ret); ++} ++ ++Buffer *compute_exchange_key(EVP_PKEY *cust, EVP_PKEY *host, GError **err) ++{ ++ g_autoptr(Buffer) raw = buffer_alloc(70); ++ g_autoptr(Buffer) ret = NULL; ++ g_autoptr(Buffer) key = NULL; ++ guchar *data; ++ ++ key = derive_key(cust, host, err); ++ if (!key) ++ return NULL; ++ ++ g_assert(key->size == 66); ++ g_assert(key->size < raw->size); ++ ++ /* ANSI X.9.63-2011: 66 bytes x with leading 7 bits and ++ * concatenate 32 bit int '1' ++ */ ++ memcpy(raw->data, key->data, key->size); ++ data = raw->data; ++ data[66] = 0x00; ++ data[67] = 0x00; ++ data[68] = 0x00; ++ data[69] = 0x01; ++ ++ ret = sha256_buffer(raw, err); ++ if (!ret) ++ return NULL; ++ ++ return g_steal_pointer(&ret); ++} ++ ++gint generate_tweak(union tweak *tweak, uint16_t i, GError **err) ++{ ++ tweak->cmp_idx.idx = GUINT16_TO_BE(i); ++ if (RAND_bytes(tweak->cmp_idx.rand, sizeof(tweak->cmp_idx.rand)) != 1) { ++ g_set_error(err, PV_CRYPTO_ERROR, PV_CRYPTO_ERROR_RANDOMIZATION, ++ _("Generating a tweak failed because the required amount of random data is not available")); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static Buffer *generate_rand_data(guint size, const gchar *err_msg, ++ GError **err) ++{ ++ g_autoptr(Buffer) buf = buffer_alloc(size); ++ ++ g_assert(size <= INT_MAX); ++ ++ if (RAND_bytes(buf->data, (int)size) != 1) { ++ g_set_error_literal(err, PV_CRYPTO_ERROR, ++ PV_CRYPTO_ERROR_RANDOMIZATION, ++ err_msg); ++ return NULL; ++ } ++ ++ return g_steal_pointer(&buf); ++} ++ ++Buffer *generate_aes_iv(guint size, GError **err) ++{ ++ return generate_rand_data(size, ++ _("Generating a IV failed because the required amount of random data is not available"), ++ err); ++} ++ ++Buffer *generate_aes_key(guint size, GError **err) ++{ ++ return generate_rand_data(size, ++ _("Generating a key failed because the required amount of random data is not available"), ++ err); ++} ++ ++EVP_PKEY *generate_ec_key(gint nid, GError **err) ++{ ++ g_autoptr(EVP_PKEY_CTX) ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL); ++ g_autoptr(EVP_PKEY) ret = NULL; ++ ++ if (!ctx) ++ g_abort(); ++ ++ if (EVP_PKEY_keygen_init(ctx) != 1) { ++ g_set_error(err, PV_CRYPTO_ERROR, PV_CRYPTO_ERROR_KEYGENERATION, ++ _("EC key could not be auto-generated")); ++ return NULL; ++ } ++ ++ if (EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid) != 1) { ++ g_set_error(err, PV_CRYPTO_ERROR, PV_CRYPTO_ERROR_KEYGENERATION, ++ _("EC key could not be auto-generated")); ++ return NULL; ++ } ++ ++ if (EVP_PKEY_keygen(ctx, &ret) != 1) { ++ g_set_error(err, PV_CRYPTO_ERROR, PV_CRYPTO_ERROR_KEYGENERATION, ++ _("EC key could not be auto-generated")); ++ return NULL; ++ } ++ ++ return g_steal_pointer(&ret); ++} ++ ++static gboolean certificate_uses_correct_curve(EVP_PKEY *key, gint nid, ++ GError **err) ++{ ++ g_autoptr(EC_KEY) ec = NULL; ++ gint rc; ++ ++ g_assert(key); ++ ++ if (EVP_PKEY_id(key) != EVP_PKEY_EC) { ++ g_set_error(err, PV_CRYPTO_ERROR, PV_CRYPTO_ERROR_INVALID_PARM, ++ _("No EC key found")); ++ return FALSE; ++ } ++ ++ ec = EVP_PKEY_get1_EC_KEY(key); ++ if (!ec) { ++ g_set_error(err, PV_CRYPTO_ERROR, PV_CRYPTO_ERROR_INVALID_PARM, ++ _("No EC key found")); ++ return FALSE; ++ } ++ ++ if (EC_KEY_check_key(ec) != 1) { ++ g_set_error(err, PV_CRYPTO_ERROR, PV_CRYPTO_ERROR_INVALID_PARM, ++ _("Invalid EC key")); ++ return FALSE; ++ } ++ ++ rc = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec)); ++ if (rc != nid) { ++ /* maybe the NID is unset */ ++ if (rc == 0) { ++ g_autoptr(EC_GROUP) grp = EC_GROUP_new_by_curve_name(nid); ++ const EC_POINT *pub = EC_KEY_get0_public_key(ec); ++ g_autoptr(BN_CTX) ctx = BN_CTX_new(); ++ ++ if (EC_POINT_is_on_curve(grp, pub, ctx) != 1) { ++ g_set_error_literal(err, PV_CRYPTO_ERROR, ++ PV_CRYPTO_ERROR_INVALID_PARM, ++ _("Invalid EC curve")); ++ return FALSE; ++ } ++ } else { ++ /* NID was set but doesn't match with the expected NID ++ */ ++ g_set_error(err, PV_CRYPTO_ERROR, ++ PV_CRYPTO_ERROR_INVALID_PARM, ++ _("Wrong NID used: '%d'"), ++ EC_GROUP_get_curve_name(EC_KEY_get0_group(ec))); ++ return FALSE; ++ } ++ } ++ ++ return TRUE; ++} ++ ++static gboolean verify_certificate(X509_STORE *store, X509 *cert, GError **err) ++{ ++ g_autoptr(X509_STORE_CTX) csc = X509_STORE_CTX_new(); ++ if (!csc) ++ g_abort(); ++ ++ if (X509_STORE_CTX_init(csc, store, cert, NULL) != 1) { ++ g_set_error(err, PV_CRYPTO_ERROR, PV_CRYPTO_ERROR_INIT, ++ _("Failed to initialize X.509 store")); ++ return FALSE; ++ } ++ ++ if (X509_verify_cert(csc) != 1) { ++ g_set_error(err, PV_CRYPTO_ERROR, PV_CRYPTO_ERROR_VERIFICATION, ++ _("Failed to verify host-key document")); ++ return FALSE; ++ } ++ ++ return TRUE; ++} ++ ++static X509 *load_certificate(const gchar *path, GError **err) ++{ ++ g_autoptr(X509) ret = NULL; ++ g_autoptr(BIO) bio = BIO_new_file(path, "rb"); ++ ++ if (!bio) { ++ g_set_error(err, PV_CRYPTO_ERROR, ++ PV_CRYPTO_ERROR_READ_CERTIFICATE, ++ _("Failed to read host-key document: '%s'"), path); ++ return NULL; ++ } ++ ++ ret = PEM_read_bio_X509(bio, NULL, 0, NULL); ++ if (!ret) { ++ g_set_error(err, PV_CRYPTO_ERROR, ++ PV_CRYPTO_ERROR_READ_CERTIFICATE, ++ _("Failed to load host-key document: '%s'"), path); ++ return NULL; ++ } ++ ++ return g_steal_pointer(&ret); ++} ++ ++EVP_PKEY *read_ec_pubkey_cert(X509_STORE *store, gint nid, const gchar *path, ++ GError **err) ++{ ++ g_autoptr(EVP_PKEY) ret = NULL; ++ g_autoptr(X509) cert = NULL; ++ ++ cert = load_certificate(path, err); ++ if (!cert) ++ return NULL; ++ ++ if (store && !verify_certificate(store, cert, err)) { ++ g_prefix_error(err, ++ _("Failed to load host-key document: '%s': "), ++ path); ++ return NULL; ++ } ++ ++ ret = X509_get_pubkey(cert); ++ if (!ret) { ++ g_set_error(err, PV_CRYPTO_ERROR, PV_CRYPTO_ERROR_INVALID_PARM, ++ _("Failed to get public key from host-key document: '%s'"), ++ path); ++ return NULL; ++ } ++ ++ if (!certificate_uses_correct_curve(ret, nid, err)) { ++ g_prefix_error(err, ++ _("Failed to load host-key document: '%s': "), ++ path); ++ return NULL; ++ } ++ ++ return g_steal_pointer(&ret); ++} ++ ++static gint __encrypt_decrypt_bio(const struct cipher_parms *parms, BIO *b_in, ++ BIO *b_out, gsize *size_in, gsize *size_out, ++ gboolean encrypt, GError **err) ++{ ++ gint num_bytes_read, num_bytes_written; ++ g_autoptr(EVP_CIPHER_CTX) ctx = NULL; ++ g_autoptr(BIGNUM) tweak_num = NULL; ++ const EVP_CIPHER *cipher = parms->cipher; ++ gint cipher_block_size = EVP_CIPHER_block_size(cipher); ++ guchar in_buf[PAGE_SIZE], ++ out_buf[PAGE_SIZE + (guint)cipher_block_size]; ++ const Buffer *key = parms->key; ++ const Buffer *tweak = parms->iv_or_tweak; ++ g_autofree guchar *tmp_tweak = NULL; ++ gint out_len, tweak_size; ++ gsize tmp_size_in = 0, tmp_size_out = 0; ++ ++ g_assert(cipher_block_size > 0); ++ g_assert(key); ++ g_assert(tweak); ++ g_assert(tweak->size <= INT_MAX); ++ ++ /* copy the value for leaving the original value untouched */ ++ tmp_tweak = g_malloc0(tweak->size); ++ memcpy(tmp_tweak, tweak->data, tweak->size); ++ tweak_size = (int)tweak->size; ++ tweak_num = BN_bin2bn(tmp_tweak, tweak_size, NULL); ++ if (!tweak_num) { ++ g_set_error(err, PV_CRYPTO_ERROR, PV_CRYPTO_ERROR_INTERNAL, ++ _("BN_bin2bn failed")); ++ return -1; ++ } ++ ++ ctx = EVP_CIPHER_CTX_new(); ++ if (!ctx) ++ g_abort(); ++ ++ /* don't set the key or tweak right away as we want to check ++ * lengths before ++ */ ++ if (EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, encrypt) != 1) { ++ g_set_error(err, PV_CRYPTO_ERROR, PV_CRYPTO_ERROR_INTERNAL, ++ _("EVP_CipherInit_ex failed")); ++ return -1; ++ } ++ ++ /* Now we can set the key and tweak */ ++ if (EVP_CipherInit_ex(ctx, NULL, NULL, key->data, tmp_tweak, encrypt) != ++ 1) { ++ g_set_error(err, PV_CRYPTO_ERROR, PV_CRYPTO_ERROR_INTERNAL, ++ _("EVP_CipherInit_ex failed")); ++ return -1; ++ } ++ ++ do { ++ memset(in_buf, 0, sizeof(in_buf)); ++ /* Read in data in 4096 bytes blocks. Update the ciphering ++ * with each read. ++ */ ++ num_bytes_read = BIO_read(b_in, in_buf, (int)PAGE_SIZE); ++ if (num_bytes_read < 0) { ++ g_set_error(err, PV_CRYPTO_ERROR, ++ PV_CRYPTO_ERROR_INTERNAL, ++ _("Failed to read")); ++ return -1; ++ } ++ tmp_size_in += (guint)num_bytes_read; ++ ++ /* in case we reached the end and it's not the special ++ * case of an empty component we can break here ++ */ ++ if (num_bytes_read == 0 && tmp_size_in != 0) ++ break; ++ ++ if (EVP_CipherUpdate(ctx, out_buf, &out_len, in_buf, ++ sizeof(in_buf)) != 1) { ++ g_set_error(err, PV_CRYPTO_ERROR, ++ PV_CRYPTO_ERROR_INTERNAL, ++ _("EVP_CipherUpdate failed")); ++ return -1; ++ } ++ g_assert(out_len >= 0); ++ ++ num_bytes_written = BIO_write(b_out, out_buf, out_len); ++ if (num_bytes_written < 0) { ++ g_set_error(err, PV_CRYPTO_ERROR, ++ PV_CRYPTO_ERROR_INTERNAL, ++ _("Failed to write")); ++ return -1; ++ } ++ g_assert(num_bytes_written == out_len); ++ ++ tmp_size_out += (guint)num_bytes_written; ++ ++ /* Set new tweak value. Please keep in mind that the ++ * tweaks are stored in big-endian form. Therefore we ++ * must use the correct OpenSSL functions ++ */ ++ if (BN_add_word(tweak_num, PAGE_SIZE) != 1) { ++ g_set_error(err, PV_CRYPTO_ERROR, ++ PV_CRYPTO_ERROR_INTERNAL, ++ _("BN_add_word failed")); ++ } ++ g_assert(BN_num_bytes(tweak_num) > 0); ++ g_assert(BN_num_bytes(tweak_num) <= tweak_size); ++ ++ if (BN_bn2binpad(tweak_num, tmp_tweak, tweak_size) < 0) { ++ g_set_error(err, PV_CRYPTO_ERROR, ++ PV_CRYPTO_ERROR_INTERNAL, ++ _("BN_bn2binpad failed")); ++ }; ++ ++ /* set new tweak */ ++ if (EVP_CipherInit_ex(ctx, NULL, NULL, NULL, tmp_tweak, ++ encrypt) != 1) { ++ g_set_error(err, PV_CRYPTO_ERROR, ++ PV_CRYPTO_ERROR_INTERNAL, ++ _("EVP_CipherInit_ex failed")); ++ return -1; ++ } ++ } while (num_bytes_read == PAGE_SIZE); ++ ++ /* Now cipher the final block and write it out to file */ ++ if (EVP_CipherFinal_ex(ctx, out_buf, &out_len) != 1) { ++ g_set_error(err, PV_CRYPTO_ERROR, PV_CRYPTO_ERROR_INTERNAL, ++ _("EVP_CipherFinal_ex failed")); ++ return -1; ++ } ++ g_assert(out_len >= 0); ++ ++ num_bytes_written = BIO_write(b_out, out_buf, out_len); ++ if (num_bytes_written < 0) { ++ g_set_error(err, PV_CRYPTO_ERROR, PV_CRYPTO_ERROR_INTERNAL, ++ _("Failed to write")); ++ return -1; ++ } ++ g_assert(out_len == num_bytes_written); ++ tmp_size_out += (guint)out_len; ++ ++ if (BIO_flush(b_out) != 1) { ++ g_set_error(err, PV_CRYPTO_ERROR, PV_CRYPTO_ERROR_INTERNAL, ++ _("Failed to flush")); ++ return -1; ++ } ++ ++ *size_in = tmp_size_in; ++ *size_out = tmp_size_out; ++ return 0; ++} ++ ++static Buffer *__encrypt_decrypt_buffer(const struct cipher_parms *parms, ++ const Buffer *in, gboolean encrypt, ++ GError **err) ++{ ++ g_autoptr(Buffer) ret = NULL; ++ g_autoptr(BIO) b_out = NULL; ++ g_autoptr(BIO) b_in = NULL; ++ gsize in_size, out_size; ++ gchar *data = NULL; ++ long data_size; ++ ++ g_assert(in->size <= INT_MAX); ++ ++ b_in = BIO_new_mem_buf(in->data, (int)in->size); ++ if (!b_in) ++ g_abort(); ++ ++ b_out = BIO_new(BIO_s_mem()); ++ if (!b_out) ++ g_abort(); ++ ++ if (__encrypt_decrypt_bio(parms, b_in, b_out, &in_size, &out_size, ++ encrypt, err) < 0) ++ return NULL; ++ ++ data_size = BIO_get_mem_data(b_out, &data); ++ if (data_size < 0) { ++ g_set_error(err, PV_CRYPTO_ERROR, PV_CRYPTO_ERROR_INTERNAL, ++ _("Could not read buffer")); ++ return NULL; ++ } ++ ++ ret = buffer_alloc((unsigned long)data_size); ++ memcpy(ret->data, data, ret->size); ++ return g_steal_pointer(&ret); ++} ++ ++Buffer *encrypt_buf(const struct cipher_parms *parms, const Buffer *in, ++ GError **err) ++{ ++ return __encrypt_decrypt_buffer(parms, in, TRUE, err); ++} ++ ++Buffer *decrypt_buf(const struct cipher_parms *parms, const Buffer *in, ++ GError **err) ++{ ++ return __encrypt_decrypt_buffer(parms, in, FALSE, err); ++} ++ ++static gint __encrypt_decrypt_file(const struct cipher_parms *parms, ++ const gchar *path_in, const gchar *path_out, ++ gsize *size_in, gsize *size_out, gboolean encrypt, ++ GError **err) ++{ ++ g_autoptr(BIO) b_out = NULL; ++ g_autoptr(BIO) b_in = NULL; ++ ++ b_in = BIO_new_file(path_in, "rb"); ++ if (!b_in) { ++ g_set_error(err, PV_CRYPTO_ERROR, ++ PV_CRYPTO_ERROR_READ_CERTIFICATE, ++ _("Failed to read file '%s'"), path_in); ++ return -1; ++ } ++ ++ b_out = BIO_new_file(path_out, "wb"); ++ if (!b_out) { ++ g_set_error(err, PV_CRYPTO_ERROR, ++ PV_CRYPTO_ERROR_READ_CERTIFICATE, ++ _("Failed to write file '%s'"), path_out); ++ return -1; ++ } ++ ++ if (__encrypt_decrypt_bio(parms, b_in, b_out, size_in, size_out, ++ encrypt, err) < 0) ++ return -1; ++ ++ return 0; ++} ++ ++gint encrypt_file(const struct cipher_parms *parms, const gchar *path_in, ++ const gchar *path_out, gsize *in_size, gsize *out_size, ++ GError **err) ++{ ++ return __encrypt_decrypt_file(parms, path_in, path_out, in_size, ++ out_size, TRUE, err); ++} ++ ++G_GNUC_UNUSED static gint decrypt_file(const struct cipher_parms *parms, ++ const gchar *path_in, const gchar *path_out, ++ gsize *in_size, gsize *out_size, ++ GError **err) ++{ ++ return __encrypt_decrypt_file(parms, path_in, path_out, in_size, ++ out_size, FALSE, err); ++} ++ ++/* GCM mode uses (zero-)padding */ ++static int64_t gcm_encrypt_decrypt(const Buffer *in, const Buffer *aad, ++ const struct cipher_parms *parms, ++ Buffer *out, Buffer *tag, ++ enum PvCryptoMode mode, GError **err) ++{ ++ g_autoptr(EVP_CIPHER_CTX) ctx = NULL; ++ const EVP_CIPHER *cipher = parms->cipher; ++ const Buffer *iv = parms->iv_or_tweak; ++ gboolean encrypt = mode == PV_ENCRYPT; ++ const Buffer *key = parms->key; ++ int64_t ret = -1; ++ gint len = -1; ++ ++ g_assert(cipher); ++ g_assert(key); ++ g_assert(iv); ++ /* Checks for later casts */ ++ g_assert(aad->size <= INT_MAX); ++ g_assert(in->size <= INT_MAX); ++ g_assert(tag->size <= INT_MAX); ++ g_assert(iv->size <= INT_MAX); ++ g_assert(out->size == in->size); ++ ++ ctx = EVP_CIPHER_CTX_new(); ++ if (!ctx) ++ g_abort(); ++ ++ /* First, set the cipher algorithm so we can verify our key/IV lengths ++ */ ++ if (EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, encrypt) != 1) { ++ g_set_error(err, PV_CRYPTO_ERROR, PV_CRYPTO_ERROR_INTERNAL, ++ _("EVP_CIPHER_CTX_new failed")); ++ return -1; ++ } ++ ++ /* Set IV length */ ++ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, (int)iv->size, NULL) != 1) { ++ g_set_error(err, PV_CRYPTO_ERROR, PV_CRYPTO_ERROR_INTERNAL, ++ _("EVP_CIPHER_CTX_ex failed")); ++ return -1; ++ } ++ ++ /* Initialise key and IV */ ++ if (EVP_CipherInit_ex(ctx, NULL, NULL, key->data, iv->data, encrypt) != ++ 1) { ++ g_set_error(err, PV_CRYPTO_ERROR, PV_CRYPTO_ERROR_INTERNAL, ++ _("EVP_CipherInit_ex failed")); ++ return -1; ++ } ++ ++ if (aad->size > 0) { ++ /* Provide any AAD data */ ++ if (EVP_CipherUpdate(ctx, NULL, &len, aad->data, ++ (int)aad->size) != 1) { ++ g_set_error(err, PV_CRYPTO_ERROR, ++ PV_CRYPTO_ERROR_INTERNAL, ++ _("EVP_CipherUpdate failed")); ++ return -1; ++ } ++ g_assert(len == (int)aad->size); ++ } ++ ++ /* Provide data to be en/decrypted */ ++ if (EVP_CipherUpdate(ctx, out->data, &len, in->data, (int)in->size) != 1) { ++ g_set_error(err, PV_CRYPTO_ERROR, PV_CRYPTO_ERROR_INTERNAL, ++ _("EVP_CipherUpdate failed")); ++ return -1; ++ } ++ ret = len; ++ ++ if (!encrypt) { ++ /* Set expected tag value */ ++ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, ++ (int)tag->size, tag->data) != 1) { ++ g_set_error(err, PV_CRYPTO_ERROR, ++ PV_CRYPTO_ERROR_INTERNAL, ++ _("Setting the GCM tag failed")); ++ return -1; ++ } ++ } ++ ++ /* Finalize the en/decryption */ ++ if (EVP_CipherFinal_ex(ctx, (guchar *)out->data + len, &len) != 1) { ++ g_set_error(err, PV_CRYPTO_ERROR, PV_CRYPTO_ERROR_INTERNAL, ++ _("EVP_CipherFinal_ex failed")); ++ return -1; ++ } ++ ret += len; ++ ++ if (encrypt) { ++ /* Get the tag */ ++ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, ++ (int)tag->size, tag->data) != 1) { ++ g_set_error(err, PV_CRYPTO_ERROR, ++ PV_CRYPTO_ERROR_INTERNAL, ++ _("Getting the GCM tag failed")); ++ return -1; ++ } ++ } ++ ++ g_assert(ret == (int)in->size); ++ return ret; ++} ++ ++int64_t gcm_encrypt(const Buffer *in, const Buffer *aad, ++ const struct cipher_parms *parms, Buffer *out, Buffer *tag, ++ GError **err) ++{ ++ return gcm_encrypt_decrypt(in, aad, parms, out, tag, PV_ENCRYPT, err); ++} +--- /dev/null ++++ b/genprotimg/src/utils/crypto.h +@@ -0,0 +1,104 @@ ++/* ++ * General cryptography helper functions and definitions ++ * ++ * Copyright IBM Corp. 2020 ++ * ++ * s390-tools is free software; you can redistribute it and/or modify ++ * it under the terms of the MIT license. See LICENSE for details. ++ */ ++ ++#ifndef PV_UTILS_CRYPTO_H ++#define PV_UTILS_CRYPTO_H ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "common.h" ++#include "include/pv_crypto_def.h" ++#include "lib/zt_common.h" ++ ++#include "buffer.h" ++ ++#define AES_256_GCM_IV_SIZE 12 ++#define AES_256_GCM_TAG_SIZE 16 ++ ++#define AES_256_XTS_TWEAK_SIZE 16 ++#define AES_256_XTS_KEY_SIZE 64 ++ ++enum PvCryptoMode { ++ PV_ENCRYPT, ++ PV_DECRYPT, ++}; ++ ++typedef GSList HostKeyList; ++ ++/* Register auto cleanup functions */ ++WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(BIGNUM, BN_free) ++WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(BIO, BIO_free_all) ++WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(BN_CTX, BN_CTX_free) ++WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(EC_GROUP, EC_GROUP_free) ++WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(EC_KEY, EC_KEY_free) ++WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(EC_POINT, EC_POINT_free) ++WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(EVP_CIPHER_CTX, EVP_CIPHER_CTX_free) ++WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(EVP_MD_CTX, EVP_MD_CTX_free) ++WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(EVP_PKEY, EVP_PKEY_free) ++WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(EVP_PKEY_CTX, EVP_PKEY_CTX_free) ++WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(X509, X509_free) ++WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(X509_LOOKUP, X509_LOOKUP_free) ++WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(X509_STORE, X509_STORE_free) ++WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(X509_STORE_CTX, X509_STORE_CTX_free) ++ ++union cmp_index { ++ struct { ++ uint16_t idx; ++ guchar rand[6]; ++ } __packed; ++ uint64_t data; ++}; ++ ++/* The tweak is always stored in big endian format */ ++union tweak { ++ struct { ++ union cmp_index cmp_idx; ++ uint64_t page_idx; /* page index */ ++ } __packed; ++ uint8_t data[AES_256_XTS_TWEAK_SIZE]; ++}; ++ ++struct cipher_parms { ++ const EVP_CIPHER *cipher; ++ const Buffer *key; ++ const Buffer *iv_or_tweak; ++}; ++ ++EVP_PKEY *read_ec_pubkey_cert(X509_STORE *store, gint nid, const gchar *path, ++ GError **err); ++Buffer *compute_exchange_key(EVP_PKEY *cust, EVP_PKEY *host, GError **err); ++Buffer *generate_aes_key(guint size, GError **err); ++Buffer *generate_aes_iv(guint size, GError **err); ++EVP_PKEY *generate_ec_key(gint nid, GError **err); ++gint generate_tweak(union tweak *tweak, uint16_t i, GError **err); ++union ecdh_pub_key *evp_pkey_to_ecdh_pub_key(EVP_PKEY *key, GError **err); ++EVP_MD_CTX *digest_ctx_new(const EVP_MD *md, GError **err); ++Buffer *digest_ctx_finalize(EVP_MD_CTX *ctx, GError **err); ++Buffer *sha256_buffer(const Buffer *buf, GError **err); ++int64_t gcm_encrypt(const Buffer *in, const Buffer *aad, ++ const struct cipher_parms *parms, Buffer *out, ++ Buffer *tag, GError **err); ++gint encrypt_file(const struct cipher_parms *parms, const gchar *in_path, ++ const gchar *path_out, gsize *in_size, gsize *out_size, ++ GError **err); ++Buffer *encrypt_buf(const struct cipher_parms *parms, const Buffer *in, ++ GError **err); ++G_GNUC_UNUSED Buffer *decrypt_buf(const struct cipher_parms *parms, ++ const Buffer *in, GError **err); ++ ++#endif +--- /dev/null ++++ b/genprotimg/src/utils/file_utils.c +@@ -0,0 +1,234 @@ ++/* ++ * General file utils ++ * ++ * Copyright IBM Corp. 2020 ++ * ++ * s390-tools is free software; you can redistribute it and/or modify ++ * it under the terms of the MIT license. See LICENSE for details. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "pv/pv_error.h" ++ ++#include "align.h" ++#include "buffer.h" ++#include "common.h" ++#include "file_utils.h" ++ ++FILE *file_open(const gchar *filename, const gchar *mode, GError **err) ++{ ++ FILE *f = fopen(filename, mode); ++ ++ if (!f) { ++ g_set_error(err, G_FILE_ERROR, ++ (gint)g_file_error_from_errno(errno), ++ _("Failed to open file '%s': %s"), filename, ++ g_strerror(errno)); ++ return NULL; ++ } ++ ++ return f; ++} ++ ++gint file_size(const gchar *filename, gsize *size, GError **err) ++{ ++ GStatBuf st_buf; ++ ++ g_assert(size); ++ ++ if (g_stat(filename, &st_buf) != 0) { ++ g_set_error(err, G_FILE_ERROR, ++ (gint)g_file_error_from_errno(errno), ++ _("Failed to get file status '%s': %s"), filename, ++ g_strerror(errno)); ++ return -1; ++ } ++ ++ if (!S_ISREG(st_buf.st_mode)) { ++ g_set_error(err, G_FILE_ERROR, PV_ERROR_INTERNAL, ++ _("File '%s' is not a regular file"), filename); ++ return -1; ++ } ++ ++ if (st_buf.st_size < 0) { ++ g_set_error(err, G_FILE_ERROR, PV_ERROR_INTERNAL, ++ _("Invalid file size for '%s': %zu"), filename, ++ st_buf.st_size); ++ return -1; ++ } ++ ++ *size = (gsize)st_buf.st_size; ++ return 0; ++} ++ ++/* Returns 0 on success, otherwise -1. Stores the total number of ++ * elements successfully read in @count_read ++ */ ++gint file_read(FILE *in, void *ptr, gsize size, gsize count, ++ gsize *count_read, GError **err) ++{ ++ gsize tmp_count_read; ++ ++ tmp_count_read = fread(ptr, size, count, in); ++ if (count_read) ++ *count_read = tmp_count_read; ++ ++ if (ferror(in)) { ++ g_set_error(err, G_FILE_ERROR, 0, _("Failed to read file")); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++gint file_write(FILE *out, const void *ptr, gsize size, gsize count, ++ gsize *count_written, GError **err) ++{ ++ gsize tmp_count_written; ++ ++ tmp_count_written = fwrite(ptr, size, count, out); ++ if (count_written) ++ *count_written = tmp_count_written; ++ ++ if (tmp_count_written != count || ferror(out)) { ++ g_set_error(err, G_FILE_ERROR, 0, _("Failed to write file")); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static gint file_seek(FILE *f, uint64_t offset, GError **err) ++{ ++ gint rc; ++ ++ if (offset > LONG_MAX) { ++ g_set_error(err, PV_ERROR, 0, _("Offset is too large")); ++ return -1; ++ } ++ ++ rc = fseek(f, (long)offset, SEEK_SET); ++ if (rc != 0) { ++ g_set_error(err, G_FILE_ERROR, ++ (gint)g_file_error_from_errno(errno), ++ _("Failed to seek: '%s'"), g_strerror(errno)); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++gint seek_and_write_file(FILE *o, const CompFile *ifile, uint64_t offset, ++ GError **err) ++{ ++ gsize bytes_read, bytes_written; ++ gsize total_bytes_read = 0; ++ FILE *i = NULL; ++ gchar buf[4096]; ++ gint ret = -1; ++ ++ if (file_seek(o, offset, err) < 0) ++ return -1; ++ ++ i = file_open(ifile->path, "rb", err); ++ if (!i) ++ return -1; ++ ++ do { ++ if (file_read(i, buf, 1, sizeof(buf), &bytes_read, err) < 0) { ++ g_prefix_error(err, _("Failed to read file '%s': "), ++ ifile->path); ++ goto err; ++ } ++ ++ if (bytes_read == 0) ++ break; ++ ++ total_bytes_read += bytes_read; ++ ++ if (file_write(o, buf, bytes_read, 1, &bytes_written, err) < 0) ++ goto err; ++ } while (bytes_written != 0); ++ ++ if (ifile->size != total_bytes_read) { ++ g_set_error(err, PV_ERROR, PV_ERROR_INTERNAL, ++ _("'%s' has changed during the preparation"), ++ ifile->path); ++ goto err; ++ } ++ ++ ret = 0; ++err: ++ fclose(i); ++ return ret; ++} ++ ++gint seek_and_write_buffer(FILE *o, const Buffer *buf, uint64_t offset, ++ GError **err) ++{ ++ if (file_seek(o, offset, err) < 0) ++ return -1; ++ ++ if (buffer_write(buf, o, err) < 0) ++ return -1; ++ ++ return 0; ++} ++ ++gint pad_file_right(const gchar *path_out, const gchar *path_in, gsize *size_out, ++ guint padding, GError **err) ++{ ++ FILE *f_in, *f_out = NULL; ++ guchar buf[padding]; ++ gsize num_bytes_written; ++ gsize num_bytes_read; ++ uint64_t size_in = 0; ++ gint ret = -1; ++ ++ *size_out = 0; ++ f_in = file_open(path_in, "rb", err); ++ if (!f_in) ++ goto err; ++ ++ f_out = file_open(path_out, "wb", err); ++ if (!f_out) ++ goto err; ++ ++ do { ++ memset(buf, 0, sizeof(buf)); ++ ++ if (file_read(f_in, buf, 1, sizeof(buf), &num_bytes_read, err) < 0) { ++ g_prefix_error(err, _("Failed to read file '%s': "), ++ path_in); ++ goto err; ++ } ++ ++ size_in += num_bytes_read; ++ ++ if (file_write(f_out, buf, 1, sizeof(buf), &num_bytes_written, err)) { ++ g_prefix_error(err, _("Failed to write file '%s': "), ++ path_out); ++ goto err; ++ } ++ ++ *size_out += num_bytes_written; ++ } while (num_bytes_read == padding); ++ ++ g_assert(num_bytes_written == ALIGN(num_bytes_read, padding)); ++ ++ ret = 0; ++err: ++ if (f_out) ++ fclose(f_out); ++ if (f_in) ++ fclose(f_in); ++ return ret; ++} +--- /dev/null ++++ b/genprotimg/src/utils/file_utils.h +@@ -0,0 +1,34 @@ ++/* ++ * General file utils ++ * ++ * Copyright IBM Corp. 2020 ++ * ++ * s390-tools is free software; you can redistribute it and/or modify ++ * it under the terms of the MIT license. See LICENSE for details. ++ */ ++ ++#ifndef PV_FILE_UTILS_H ++#define PV_FILE_UTILS_H ++ ++#include ++#include ++#include ++ ++#include "pv/pv_comp.h" ++ ++#include "buffer.h" ++ ++FILE *file_open(const gchar *filename, const gchar *mode, GError **err); ++gint file_size(const gchar *filename, gsize *size, GError **err); ++gint file_read(FILE *in, void *ptr, gsize size, gsize count, ++ gsize *count_read, GError **err); ++gint file_write(FILE *out, const void *ptr, gsize size, gsize count, ++ gsize *count_written, GError **err); ++gint pad_file_right(const gchar *path_out, const gchar *path_in, ++ gsize *size_out, guint padding, GError **err); ++gint seek_and_write_buffer(FILE *out, const Buffer *buf, uint64_t offset, ++ GError **err); ++gint seek_and_write_file(FILE *o, const CompFile *ifile, uint64_t offset, ++ GError **err); ++ ++#endif +--- a/include/boot/ipl.h ++++ b/include/boot/ipl.h +@@ -18,6 +18,11 @@ + #define IPL_RB_COMPONENT_FLAG_SIGNED 0x80 + #define IPL_RB_COMPONENT_FLAG_VERIFIED 0x40 + ++#define IPL_PARM_BLOCK_VERSION 0x1 ++ ++/* IPL Types */ ++#define IPL_TYPE_PV 0x5 ++ + + #ifndef __ASSEMBLER__ + diff --git a/s390-tools.changes b/s390-tools.changes index 6c7672b..b45c413 100644 --- a/s390-tools.changes +++ b/s390-tools.changes @@ -1,3 +1,73 @@ +------------------------------------------------------------------- +Thu Mar 19 19:22:19 UTC 2020 - Mark Post + +- Added the following patches for bsc#1166850 + zipl: fix secure boot config handling: + * s390-tools-sles15sp2-01-zipl-Add-missing-options-to-help-output.patch + * s390-tools-sles15sp2-02-zipl-allow-stand-alone-secure-option-on-command-l.patch + * s390-tools-sles15sp2-03-zipl-correct-secure-boot-config-handling.patch + * s390-tools-sles15sp2-04-zipl-fix-zipl.conf-man-page-example-for-secure-boot.patch +- Modified the spec file so that the kernel used for the SCSI dump + tool is named zfcpdump-image instead of zfcpdump_part.image. This + is to match the new version of zipl that expects this new file name. + (bsc#1166851) + +------------------------------------------------------------------- +Wed Mar 18 17:58:57 UTC 2020 - Mark Post + +- Added the following patches to implement jsc#SLE-7471, Enhanced + tooling for kvm guest images (bsc#1165549): + * s390-tools-sles15sp2-01-zipl-fix-Wdiscarded-qualifiers.patch + * s390-tools-sles15sp2-02-zipl-fix-Waddress-of-packed-member.patch + * s390-tools-sles15sp2-03-zipl-remove-some-useless-__packed___-attributes.patch + * s390-tools-sles15sp2-04-zipl-Fix-entry-point-for-stand-alone-kdump.patch + * s390-tools-sles15sp2-05-zipl-Fix-dependency-generation-in-zipl-boot.patch + * s390-tools-sles15sp2-06-zipl-Make-use-of-__packed-macro.patch + * s390-tools-sles15sp2-07-zipl-define-__section-macro-and-make-use-of-it.patch + * s390-tools-sles15sp2-08-zipl-Make-use-of-__noreturn-macro.patch + * s390-tools-sles15sp2-09-zipl-Define-__noinline-macro-and-make-use-of-it.patch + * s390-tools-sles15sp2-10-zipl-stage3-Mark-start_kernel-__noreturn.patch + * s390-tools-sles15sp2-11-zipl-sclp-Remove-duplicate-macros.patch + * s390-tools-sles15sp2-12-zipl-Make-address-size-mask-macros-UL.patch + * s390-tools-sles15sp2-13-zipl-libc-Use-stdint.h-instead-of-self-defined-macro.patch + * s390-tools-sles15sp2-14-zipl-Consolidate-IMAGE-macros.patch + * s390-tools-sles15sp2-15-zipl-Consolidate-STAGE-2-3-macros.patch + * s390-tools-sles15sp2-16-zipl-stfle-use-uint64_t-instead-of-u64.patch + * s390-tools-sles15sp2-17-zipl-boot-fix-comment-in-stage3.lds.patch + * s390-tools-sles15sp2-18-lib-zt_common-add-STATIC_ASSERT-macro.patch + * s390-tools-sles15sp2-19-zipl-use-STATIC_ASSERT-macro-for-no-padding-verifica.patch + * s390-tools-sles15sp2-20-Support-lib-zt_common.h-to-be-used-in-assembler-and-.patch + * s390-tools-sles15sp2-21-zipl-move-IPL-related-definitions-into-separate-head.patch + * s390-tools-sles15sp2-22-zipl-move-SIGP-related-functions-and-definitions-int.patch + * s390-tools-sles15sp2-23-zipl-add-SIGP_SET_ARCHITECTURE-to-sigp.h-and-use-it.patch + * s390-tools-sles15sp2-24-zipl-stage3-make-IPL_DEVICE-definition-consistent-wi.patch + * s390-tools-sles15sp2-25-zipl-move-Linux-layout-definitions-into-separate-hea.patch + * s390-tools-sles15sp2-26-zipl-tape0-use-constants-defined-in-linux_layout.h.patch + * s390-tools-sles15sp2-27-zipl-use-STAGE3_ENTRY-for-STAGE3_LOAD_ADDRESS.patch + * s390-tools-sles15sp2-28-zipl-move-loaders-layout-definitions-into-separate-h.patch + * s390-tools-sles15sp2-29-zipl-s390.h-rename-inline-macro-into-__always_inline.patch + * s390-tools-sles15sp2-30-zipl-move-__always_inline-barrier-__pa32-pa-to-zt_co.patch + * s390-tools-sles15sp2-31-zipl-make-BLK_PWRT-unsigned-int.patch + * s390-tools-sles15sp2-32-Consolidate-MIN-and-MAX-macros.patch + * s390-tools-sles15sp2-33-zipl-remove-libc.h-include-in-s390.h.patch + * s390-tools-sles15sp2-34-zipl-move-s390.h-to-include-boot-s390.h.patch + * s390-tools-sles15sp2-35-zipl-libc-include-s390.h.patch + * s390-tools-sles15sp2-36-include-boot-s390.h-move-panic-and-panic_notify-to-l.patch + * s390-tools-sles15sp2-37-include-boot-s390.h-fixes-for-Werror-sign-conversion.patch + * s390-tools-sles15sp2-38-zipl-refactor-all-EBCDIC-code-into-separate-files.patch + * s390-tools-sles15sp2-39-zipl-sclp-add-macros-for-the-control-program-masks.patch + * s390-tools-sles15sp2-40-zipl-sclp-add-sclp_print_ascii.patch + * s390-tools-sles15sp2-41-zipl-libc-printf-print-on-linemode-and-ASCII-console.patch + * s390-tools-sles15sp2-42-Consolidate-ALIGN-__ALIGN_MASK-ARRAY_SIZE-macros.patch + * s390-tools-sles15sp2-43-genprotimg-boot-initial-bootloader-support.patch + * s390-tools-sles15sp2-44-genprotimg-boot-use-C-pre-processor-for-linker-scrip.patch + * s390-tools-sles15sp2-45-genprotimg-add-relocator-for-stage3b.patch + * s390-tools-sles15sp2-46-README.md-remove-useless-empty-line.patch + * s390-tools-sles15sp2-47-include-boot-s390.h-add-guard-for-struct-__vector128.patch + * s390-tools-sles15sp2-48-genprotimg-introduce-new-tool-for-the-creation-of-PV.patch +- Added a BuildRequires for glib2-devel to support the new feature. +- Added a %dir entry for /usr/share/s390-tools/genprotimg + ------------------------------------------------------------------- Tue Mar 10 18:25:51 UTC 2020 - Mark Post diff --git a/s390-tools.spec b/s390-tools.spec index 56d2910..866136e 100644 --- a/s390-tools.spec +++ b/s390-tools.spec @@ -1,7 +1,7 @@ # # spec file for package s390-tools # -# Copyright (c) 2001-2020 SUSE LLC, Nuernberg, Germany. +# Copyright (c) 2001-2020 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -135,6 +135,58 @@ Patch45: s390-tools-sles15sp2-04-zipl-libc-Indicate-truncated-lines-in-pr Patch46: s390-tools-sles15sp2-01-zpcictl-Initiate-recover-after-reset.patch Patch47: s390-tools-sles15sp2-02-zpcictl-Rename-misleading-sysfs_write_data.patch Patch48: s390-tools-sles15sp2-03-zpcitctl-Exit-on-error-in-sysfs_report_error.patch +Patch49: s390-tools-sles15sp2-01-zipl-fix-Wdiscarded-qualifiers.patch +Patch50: s390-tools-sles15sp2-02-zipl-fix-Waddress-of-packed-member.patch +Patch51: s390-tools-sles15sp2-03-zipl-remove-some-useless-__packed___-attributes.patch +Patch52: s390-tools-sles15sp2-04-zipl-Fix-entry-point-for-stand-alone-kdump.patch +Patch53: s390-tools-sles15sp2-05-zipl-Fix-dependency-generation-in-zipl-boot.patch +Patch54: s390-tools-sles15sp2-06-zipl-Make-use-of-__packed-macro.patch +Patch55: s390-tools-sles15sp2-07-zipl-define-__section-macro-and-make-use-of-it.patch +Patch56: s390-tools-sles15sp2-08-zipl-Make-use-of-__noreturn-macro.patch +Patch57: s390-tools-sles15sp2-09-zipl-Define-__noinline-macro-and-make-use-of-it.patch +Patch58: s390-tools-sles15sp2-10-zipl-stage3-Mark-start_kernel-__noreturn.patch +Patch59: s390-tools-sles15sp2-11-zipl-sclp-Remove-duplicate-macros.patch +Patch60: s390-tools-sles15sp2-12-zipl-Make-address-size-mask-macros-UL.patch +Patch61: s390-tools-sles15sp2-13-zipl-libc-Use-stdint.h-instead-of-self-defined-macro.patch +Patch62: s390-tools-sles15sp2-14-zipl-Consolidate-IMAGE-macros.patch +Patch63: s390-tools-sles15sp2-15-zipl-Consolidate-STAGE-2-3-macros.patch +Patch64: s390-tools-sles15sp2-16-zipl-stfle-use-uint64_t-instead-of-u64.patch +Patch65: s390-tools-sles15sp2-17-zipl-boot-fix-comment-in-stage3.lds.patch +Patch66: s390-tools-sles15sp2-18-lib-zt_common-add-STATIC_ASSERT-macro.patch +Patch67: s390-tools-sles15sp2-19-zipl-use-STATIC_ASSERT-macro-for-no-padding-verifica.patch +Patch68: s390-tools-sles15sp2-20-Support-lib-zt_common.h-to-be-used-in-assembler-and-.patch +Patch69: s390-tools-sles15sp2-21-zipl-move-IPL-related-definitions-into-separate-head.patch +Patch70: s390-tools-sles15sp2-22-zipl-move-SIGP-related-functions-and-definitions-int.patch +Patch71: s390-tools-sles15sp2-23-zipl-add-SIGP_SET_ARCHITECTURE-to-sigp.h-and-use-it.patch +Patch72: s390-tools-sles15sp2-24-zipl-stage3-make-IPL_DEVICE-definition-consistent-wi.patch +Patch73: s390-tools-sles15sp2-25-zipl-move-Linux-layout-definitions-into-separate-hea.patch +Patch74: s390-tools-sles15sp2-26-zipl-tape0-use-constants-defined-in-linux_layout.h.patch +Patch75: s390-tools-sles15sp2-27-zipl-use-STAGE3_ENTRY-for-STAGE3_LOAD_ADDRESS.patch +Patch76: s390-tools-sles15sp2-28-zipl-move-loaders-layout-definitions-into-separate-h.patch +Patch77: s390-tools-sles15sp2-29-zipl-s390.h-rename-inline-macro-into-__always_inline.patch +Patch78: s390-tools-sles15sp2-30-zipl-move-__always_inline-barrier-__pa32-pa-to-zt_co.patch +Patch79: s390-tools-sles15sp2-31-zipl-make-BLK_PWRT-unsigned-int.patch +Patch80: s390-tools-sles15sp2-32-Consolidate-MIN-and-MAX-macros.patch +Patch81: s390-tools-sles15sp2-33-zipl-remove-libc.h-include-in-s390.h.patch +Patch82: s390-tools-sles15sp2-34-zipl-move-s390.h-to-include-boot-s390.h.patch +Patch83: s390-tools-sles15sp2-35-zipl-libc-include-s390.h.patch +Patch84: s390-tools-sles15sp2-36-include-boot-s390.h-move-panic-and-panic_notify-to-l.patch +Patch85: s390-tools-sles15sp2-37-include-boot-s390.h-fixes-for-Werror-sign-conversion.patch +Patch86: s390-tools-sles15sp2-38-zipl-refactor-all-EBCDIC-code-into-separate-files.patch +Patch87: s390-tools-sles15sp2-39-zipl-sclp-add-macros-for-the-control-program-masks.patch +Patch88: s390-tools-sles15sp2-40-zipl-sclp-add-sclp_print_ascii.patch +Patch89: s390-tools-sles15sp2-41-zipl-libc-printf-print-on-linemode-and-ASCII-console.patch +Patch90: s390-tools-sles15sp2-42-Consolidate-ALIGN-__ALIGN_MASK-ARRAY_SIZE-macros.patch +Patch91: s390-tools-sles15sp2-43-genprotimg-boot-initial-bootloader-support.patch +Patch92: s390-tools-sles15sp2-44-genprotimg-boot-use-C-pre-processor-for-linker-scrip.patch +Patch93: s390-tools-sles15sp2-45-genprotimg-add-relocator-for-stage3b.patch +Patch94: s390-tools-sles15sp2-46-README.md-remove-useless-empty-line.patch +Patch95: s390-tools-sles15sp2-47-include-boot-s390.h-add-guard-for-struct-__vector128.patch +Patch96: s390-tools-sles15sp2-48-genprotimg-introduce-new-tool-for-the-creation-of-PV.patch +Patch97: s390-tools-sles15sp2-01-zipl-Add-missing-options-to-help-output.patch +Patch98: s390-tools-sles15sp2-02-zipl-allow-stand-alone-secure-option-on-command-l.patch +Patch99: s390-tools-sles15sp2-03-zipl-correct-secure-boot-config-handling.patch +Patch100: s390-tools-sles15sp2-04-zipl-fix-zipl.conf-man-page-example-for-secure-boot.patch # SUSE patches Patch900: s390-tools-sles12-zipl_boot_msg.patch @@ -156,6 +208,7 @@ BuildRequires: dracut BuildRequires: fuse-devel BuildRequires: gcc-c++ BuildRequires: gettext-tools +BuildRequires: glib2-devel BuildRequires: glibc-devel-static BuildRequires: kernel-zfcpdump BuildRequires: libcryptsetup-devel > 2.0.3 @@ -270,7 +323,7 @@ install -m 755 read_values %{buildroot}/%{_bindir}/ install -m644 -t %{buildroot}/%{_mandir}/man8 %{SOURCE87} export ROOT_BUILD_DIR="%{_builddir}/%{name}-%{version}/zfcpdump/kernel" -install -D -m600 /boot/image-*-zfcpdump %{buildroot}%{_prefix}/lib/s390-tools/zfcpdump/zfcpdump_part.image +install -D -m600 /boot/image-*-zfcpdump %{buildroot}%{_prefix}/lib/s390-tools/zfcpdump/zfcpdump-image install -D -m644 etc/cpuplugd.conf %{buildroot}%{_sysconfdir}/cpuplugd.conf install -D -m644 etc/udev/rules.d/40-z90crypt.rules %{buildroot}%{_prefix}/lib/udev/rules.d/40-z90crypt.rules @@ -528,6 +581,7 @@ fi %dir %{_datadir}/s390-tools %dir %{_datadir}/s390-tools/cpumf %dir %{_datadir}/s390-tools/netboot +%dir %{_datadir}/s390-tools/genprotimg %dir %{_prefix}/lib/dracut/modules.d/95zdev %dir /boot/zipl %dir /lib/s390-tools/